高校教务管理系统 - 软件测试岗位面试题

5123 字
26 分钟
高校教务管理系统 - 软件测试岗位面试题

高校教务管理系统 - 软件测试岗位面试题#

本题集基于本项目(Vue + Spring Boot 教务系统)出题,不深挖 Java 八股,聚焦测试思维与项目落地。 技术栈:Spring Boot 2.5.6 / MyBatis / MySQL / Redis / Shiro + JWT / POI / Vue 2.7 + Element UI。 三角色:admin(level=0) / teacher(level=1) / student(level=2)。


一、项目理解#

Q1. 简单介绍下这个项目,以及你在其中负责的测试工作。#

答:这是一个高校教务管理系统,分学生、教师、管理员三种角色,核心功能包括登录认证、学生信息管理、成绩录入与导入导出、智能排课、选课、教学评估、毕业审核、数据备份与操作日志。后端 Spring Boot + MyBatis + MySQL + Redis,认证用 Shiro + JWT,前端 Vue2 + Element UI。测试工作我负责:需求评审与测试用例设计、接口测试(Postman)、功能与回归测试、结合真实缺陷做缺陷分析、以及登录/权限/成绩导入等核心模块的边界与安全测试。

Q2. 你测试时,会重点关注哪些技术风险点?#

答:

  1. 认证授权:JWT 1 小时过期 + refreshToken 24 小时,level 字段控制角色,易出越权。
  2. 数据一致性:成绩导入首次直接写入、再次提交走审批,存在状态分支。
  3. SQL 风险:teaching_class.major_id 大量 NULL,INNER JOIN 会丢数据(真实 bug)。
  4. 并发:选课余量、排课资源抢占。
  5. Excel 导入:格式校验、成绩范围 0-100、空文件。
  6. 前端联动:年级→专业→班级级联下拉的加载时序。

Q3. 三种角色的权限是怎么实现的?测试时怎么验证?#

答:前端用路由 meta.level 控制菜单与页面可见性,后端用 @UserLevel(roles={...}) 注解 + Shiro 做接口级拦截,JWT payload 里带 level 字段。测试要前后端双重验证:①前端隐藏菜单后,直接访问 URL 仍要被拦;②绕过前端直接调后端接口(带 token)应返回 403。重点测垂直越权(学生调管理员接口)和水平越权(学生 A 查学生 B 的成绩单)。

Q4. 为什么要 Shiro + JWT 一起用?#

答:JWT 负责”无状态认证”,token 自带用户信息不查库,适合前后端分离;Shiro 负责”授权”,提供角色/权限注解(@UserLevel)和过滤链,做接口级细粒度控制。两者结合 = 认证靠 JWT、授权靠 Shiro。测试关注点:token 过期/伪造/篡改、refreshToken 续期、登出后旧 token 是否仍可用(本项目无黑名单机制,是风险点)。


二、测试用例设计(结合具体功能)#

Q5. 登录功能怎么测?请给出测试点。#

答:

  • 正常:三角色正确账号密码 + 正确验证码 → 返回 token/refreshToken。
  • 账号:不存在、被禁用、level 与所选角色不匹配。
  • 密码:错误、为空、含空格、SQL 注入字符(' or 1=1 --)。
  • 验证码:空、错误、过期(>5 分钟)、大小写、重复使用(用一次后应失效)。
  • 接口层面:GET /api/sms/user/login 无参、少参、并发重复提交。
  • 安全:密码明文走 URL(GET 方式)会被浏览器历史/日志记录,是缺陷。
  • 返回值:user 为 null 时前端是否正确提示”账号或密码错误”。

Q6. 验证码功能怎么测?项目里验证码存 Redis 5 分钟,固定码 8888。#

答:

  • 正常:生成 → 输入正确 → 登录成功后 Redis 中该 uuid 被删除(一次性)。
  • 过期:等待 5 分钟后提交 → 提示”验证码已过期”。
  • 复用:同一 uuid 提交两次 → 第二次应失败。
  • 策略:captcha.strategy=fixed 时固定 8888,需测大小写、配置切换。
  • 并发/性能:高并发下 Redis 读写是否正确,uuid 是否唯一(UUID.randomUUID 理论不重复)。
  • 安全:验证码不应在响应里明文返回(仅返回 base64 图片)。

Q7. 成绩批量导入功能怎么测?(POST /api/score/import-export/class/{classId}/import)#

答:用等价类 + 边界值 + 场景法:

  • 等价类:成绩 0-100(有效)、负数、>100、非数字(字母/中文)、空、小数(如 85.5)、科学计数。
  • 边界值:0、100、59、60、-1、101。
  • 文件格式:.xlsx、.xls、.csv(应拒绝)、空文件、超大文件(50MB 限制)、模板被篡改列顺序。
  • 业务规则(判定表):①学生不在教学班 → 跳过;②行政班不在 included_classes → 跳过;③首次提交 → 直接导入;④再次提交 → 走审批;⑤学号为空 → 跳过。
  • 并发:两人同时导入同一教学班。
  • 结果校验:返回 directCount/approveCount/errorCount 是否与实际一致。

Q8. 成绩字段范围 0-100,边界值怎么取?#

答:取 0、1、59、60、99、100 六个有效边界,以及 -1、101 两个无效边界,再加小数边界(如 0.5、99.5)验证是否能存小数。结合导入导出,还要测空值(缺考/未录入)和字符串”null”的处理(项目里大量 !"null".equals(...) 判断,说明踩过坑)。

Q9. 自动排课功能怎么测?这是项目核心难点。#

答:

  • 硬约束:上午≤4节、下午≤4节、晚上≤4节、周六日不排、连堂节数、周次=ceil(总学时/连堂)且≤16。
  • 冲突检测:同一教师/教室/教学班时间冲突是否被正确识别并生成调整方案。
  • 方案生成:换教室方案、换时间方案各 ≤3 个,偏爱教室优先。
  • 边界:教室容量刚好等于人数、无可用教室、所有时段已满。
  • 二次排课:已有冲突时再次排课,方案是否为最新(防脏读,TODOLIST 里专门修过)。
  • 数据一致性:applyProposal 后 conflictList 是否同步更新。

Q10. “年级→专业→班级”三级联动下拉怎么测?#

答(对应 bug 文件夹里”班级下拉显示 ID”的真实 bug):

  • 加载时序:弹窗打开即加载 vs 依赖用户操作才加载,测首次打开是否正常。
  • 联动:改年级→专业清空重载;改专业→班级清空重载;反向回退是否残留旧值。
  • 空数据:某年级无专业、某专业无班级时下拉是否空且不报错。
  • 显示:下拉显示的是名称(如”软件工程1班”)而非主键 ID。
  • 编辑回显:打开已有记录的下拉默认选中正确项。

Q11. 成绩统计分析功能怎么测?(对应 bug3:返回 0 条数据)#

答:

  • 正常:有数据时按班级/课程/学年维度统计,图表(ECharts)渲染正确。
  • 空数据:教学班无成绩录入时,接口返回 0 条,前端是显示”暂无数据”还是报错。
  • 边界:只有 1 条成绩、全部缺考、成绩全相同(方差为 0)。
  • 筛选组合(正交法):学年 × 学期 × 年级 × 教学班 多条件交叉。
  • 数据准确性:平均分、最高分、及格率、绩点计算与数据库手动核算一致。

三、缺陷分析(结合 bug 文件夹真实 bug)#

Q12. 【bug1】编辑学生弹窗首次打开班级下拉显示 ID 而非名称,再打开又正常了。这是什么类型的 bug?怎么定位?#

答:属于状态依赖/时序 bug。根因:编辑模式 init 里调了 loadMajorList() 但没调 loadClassList(),classOptions 为空,el-select 找不到匹配项就显示绑定的 value(数字 ID)。再打开时上一次异步请求的数据残留,看起来”正常”了。定位思路:①F12 看 classOptions 是否为空;②看 init 方法是否调了 loadClassList;③对比首次与二次打开的网络请求差异。

Q13. 【bug1】这种”首次异常、再次正常”的 bug,用什么测试方法能提前发现?#

答:场景法 + 状态迁移法。等价类边界值测不出这类 bug,因为它依赖”组件是否首次初始化”。测试用例要覆盖:①首次打开弹窗(冷启动);②关闭再打开(数据残留);③切换专业后打开;④刷新页面后首次打开。核心是模拟真实操作路径,而不是孤立测单个动作。回归时要把”冷启动”作为固定用例。

Q14. 【bug2】teaching_class.major_id 为 NULL 时,INNER JOIN profession 导致查询返回空。这属于什么类型 bug?怎么测?#

答:属于数据驱动 bug,根因是 NULL 值在 INNER JOIN 时被过滤。测试方法:数据驱动测试,准备多种数据状态——major_id 为 NULL、为单个 ID、为逗号串 '1,2,3'、为不存在的 ID。用例要覆盖”脏数据”场景,不能只用理想数据。修复方案是去掉 JOIN 或改 LEFT JOIN,回归时要验证 NULL 数据能正常返回且不影响有 major_id 的记录。

Q15. 描述一个 bug 的完整生命周期。#

答:新建(New)→ 指派(Assigned)→ 开发修复(Fixed)→ 测试回归(Verified)→ 关闭(Closed)。若回归不通过则 Reopen。还有:拒绝(Rejected,非 bug)、延期(Deferred)。本项目流程:发现 bug → 写 md 归档(bug 文件夹)→ 含摘要/根因/复现/修复方案 → 修复后回归 → 关闭。

Q16. bug 的”严重程度”和”优先级”有什么区别?结合本项目举例。#

答:严重程度 = 对系统的影响程度;优先级 = 修复的紧迫性。两者不一定一致。

  • 成绩导入接口 500 错误:严重度高、优先级高。
  • 班级下拉显示 ID(bug1):严重度中(功能可用只是显示丑)、优先级中。
  • 某处文案错别字:严重度低、优先级低。
  • 严重的偶发崩溃:严重度高,但若只在极端环境复现,优先级可能中。

四、接口测试#

Q17. 怎么对这个项目做接口测试?#

答:

  1. 梳理接口清单:按模块(User/Score/Schedule/Enrollment 等)整理 URL、方法、入参、出参、权限。
  2. 环境准备:本地起后端 9121、MySQL、Redis,准备测试账号(三角色各一)。
  3. 用 Postman:建集合 → 设环境变量(token/baseURL)→ 登录用例自动提取 token 写入变量 → 后续用例引用 {{token}}。
  4. 覆盖维度:正常、异常入参、边界值、权限(越权)、幂等性。
  5. 断言:校验 HTTP 状态码 + 业务 code + 关键字段(如 directCount)。
  6. 批量执行:用 Newman 命令行跑,接入 CI。

Q18. 登录接口用 @GetMapping("/login") 传账号密码,从测试角度有什么问题?#

答:安全缺陷。GET 参数拼在 URL 上,会被浏览器历史、服务器访问日志、代理缓存、Referer 头记录,密码明文泄露风险高。应改为 POST + 请求体。测试时要点出该风险并提缺陷;同时验证 HTTPS 下是否仍走 URL(即便加密通道,日志仍会记录)。这是典型的”测试反推设计”案例。

Q19. 成绩导入接口的幂等性怎么测?#

答:幂等 = 同一请求重复执行结果一致。本项目设计:首次提交直接导入,再次提交走审批,不是技术幂等而是业务幂等。测试:①同一 Excel 导入两次,第二次应全部进审批流而非重复写入;②导入中途失败重试,不应产生重复成绩;③同一学号一条记录,不出现两条 score。验证手段:导入前后 SELECT count(*) FROM score_entry 对比。

Q20. token 过期和刷新机制怎么测?#

答:

  • 过期:token 1 小时后过期,接口返回 401,前端 axios 拦截器跳登录。
  • 刷新:refreshToken(24 小时)未过期时,应能用它换新 token,用户无感。
  • 都过期:refreshToken 也过期 → 跳登录。
  • 伪造:篡改 token payload(如改 level 从 2→0)→ 验签失败 401。
  • 登出后:本项目无黑名单,旧 token 在过期前仍可用,是风险点,应提缺陷。

五、安全测试#

Q21. 这个项目你做安全测试会关注哪些点?#

答:

  1. 越权:水平(学生 A 查 B)+ 垂直(学生调管理员接口)。
  2. 认证:JWT 密钥硬编码、token 伪造/过期、登出未失效。
  3. 注入:SQL 注入(MyBatis ${} 而非 #{} 的地方)、XSS(评教/备注字段)。
  4. 敏感信息泄露:异常信息回显 SQL/Redis 错误、密码明文 URL、application.yml 明文存 DB/Redis 密码。
  5. 文件上传:成绩导入只接受 .xlsx/.xls,防可执行文件。
  6. 验证码:可被绕过、固定码 8888 在生产是否关闭。
  7. CORS:withCredentials=true 下 Origin 是否受限。

Q22. JWT 密钥硬编码 "sms-panovo" 有什么风险?怎么验证?#

答:密钥写死在 JwtUtils.java 源码里,一旦源码泄露(如上传到公开 Git 仓库),攻击者可用该密钥伪造任意用户 token(包括 level=0 的管理员),直接接管系统。验证方式:用该密钥本地签发一个 level=0 的 token,调管理员接口,若成功则确认可伪造。修复:密钥放环境变量/配置中心,定期轮换,源码不提交。

Q23. 全局异常处理器把 SQL/Redis 错误返回给前端,有什么问题?#

答:GlobalExceptionHandler 在开发模式下把 Redis连接失败: ...、SQL 语法错误等信息塞进 message 返回。风险:信息泄露,攻击者可据错误信息推断表结构、技术栈、连接配置,辅助进一步攻击。测试应验证生产环境是否屏蔽明细(仅返回”服务异常”)。这也是安全测试用例之一。

Q24. 越权测试怎么设计?举本项目两个例子。#

答:

  • 水平越权:导出成绩单接口 GET /api/score/import-export/student/{studentId}/export,用学生 A 的 token 把 studentId 改成 B,若能拿到 B 的成绩单则越权。
  • 垂直越权:学生 token(level=2)直接访问 /api/sms/user/admin/reset-password(@UserLevel(0)),应返回 403;若能重置他人密码则严重越权。
  • 测试方法:抓包改 token / 改 path 参数 / 改 level 字段,对比预期。

六、性能测试#

Q25. 哪些场景需要做性能测试?#

答:高频、高并发、大数据量、对响应敏感的场景:

  1. 登录:开学季集中登录。
  2. 选课:抢课瞬时高并发,余量超卖是经典问题。
  3. 成绩批量导入:大文件、万级数据。
  4. 自动排课:算法复杂度高,单次排课耗时长。
  5. 成绩统计分析:聚合查询,大数据量慢查询。
  6. 首页 Dashboard:缓存命中率影响响应。

Q26. 成绩批量导入 10000 条,怎么测性能?#

答:用 JMeter:

  1. 构造 10000 行 Excel,单用户上传,测响应时间与内存占用(POI XSSFWorkbook 全量加载易 OOM)。
  2. 并发 10/50 用户同时导入不同教学班,测吞吐量 TPS。
  3. 监控后端:CPU、内存、GC、DB 连接池、Redis。
  4. 断言:导入条数 = 10000,无重复、无丢失,DB 落库一致。
  5. 瓶颈定位:若 OOM → 建议改 SAX 流式解析;若 DB 慢 → 批量 upsert 改 batch。

Q27. 排课接口响应慢,你怎么排查?#

答:

  1. 定位阶段:后端日志 + APM 看 Controller/Service/Mapper 各段耗时。
  2. SQL 层:开 MyBatis debug(项目已配 mapper: debug),看是否有 N+1 查询、全表扫描、缺索引。
  3. 算法层:排课有穷举逻辑,看时间槽/教室组合数量是否爆炸,findFirstConflict 是否做了无效遍历(TODOLIST 提过)。
  4. 缓存:高频查询是否走了 Redis。
  5. DB 层:连接池是否打满、慢查询日志。
  6. 复现后给出优化建议并回归。

七、工具与自动化#

Q28. 你用过哪些测试工具?分别用在什么场景?#

答:

  • Postman / Newman:接口测试、token 自动续期、集合批量跑、CI 集成。
  • JMeter:性能/压力测试,选课并发、导入性能。
  • Chrome DevTools / Fiddler:前端调试、抓包改包、越权测试。
  • Selenium / Cypress:UI 自动化(本项目 Element UI 适合)。
  • MySQL 客户端 + Redis CLI:数据校验。
  • Git:用例与 bug 文档版本管理。

Q29. 怎么用 Postman 实现 token 自动续期,避免每次手动改?#

答:在登录用例的 Tests 脚本里 pm.environment.set('token', responseBody.token),把 token 存入环境变量。其他用例 Header 里写 Authorization: {{token}}。token 过期返回 401 时,可在集合级前置脚本里判断 refreshToken,自动调刷新接口换新 token 再重发。本项目 axios 已实现类似逻辑,Postman 里复刻即可。

Q30. 这个项目适合做 UI 自动化吗?选型怎么考虑?#

答:适合。理由:①Vue + Element UI 组件稳定,定位器(id/role)友好;②有大量表单与列表的重复操作(增删改查、导入导出)。选型:Cypress(前端友好、调试快)或 Selenium + Python(生态成熟)。建议只自动化稳定、重复执行、回归价值高的用例(如登录、成绩 CRUD、权限校验),不追求全自动化。Element UI 用 cy.get 或 Select 选择器处理下拉。


八、测试理论(结合场景)#

Q31. 黑盒、白盒、灰盒分别是什么?结合本项目说明。#

答:

  • 黑盒:不看代码,按需求测输入输出。如测成绩导入只看 Excel → 结果。
  • 白盒:基于代码结构测,覆盖分支/语句。如看 importScores 的 if/else 分支设计用例覆盖每条路径。
  • 灰盒:结合两者,看接口/数据流但不深入实现。如测成绩导出时查 DB 落库、看接口返回 JSON 字段。 本项目我做的是灰盒为主:读 Controller/SQL 理解逻辑,再设计黑盒用例,效率最高。

Q32. 回归测试怎么做?结合排课 bugfix 说明。#

答:回归 = 修复后验证修复正确且未引入新问题。本项目排课模块改动频繁(TODOLIST 记录多次重构),回归策略:

  1. 确认修复:用原 bug 的复现用例验证已修复。
  2. 关联回归:排课涉及冲突检测、方案生成、数据一致性,相关用例全跑。
  3. 核心回归集:把登录、排课、成绩导入等核心用例固化为自动化集,每次提测自动跑。
  4. 全量回归:大版本上线前全量跑。 优先级:修复点 > 关联模块 > 核心链路 > 全量。

Q33. 冒烟测试怎么做?本项目冒烟范围是?#

答:冒烟 = 提测后快速验证核心链路通不通,不通直接打回。本项目冒烟用例:

  1. 三角色登录成功返回 token。
  2. 学生查询成绩列表、教师导出教学班成绩、管理员新增学生。
  3. 自动排课能跑通并生成课表。
  4. 成绩导入一个正常 Excel 成功。 5 个用例 5 分钟跑完,全绿才进入详细测试。

九、场景开放题#

Q34. 上线后发现成绩统计页面报 500,你的排查思路?#

答:

  1. 复现:确认是必现还是偶发,记录操作路径与参数(学年/学期/教学班)。
  2. 看日志:后端日志定位异常栈,结合 GlobalExceptionHandler 看是 SQL/Redis/空指针。
  3. 看数据:检查该教学班成绩数据是否异常(NULL、脏数据、关联缺失),参考 bug2 的 NULL JOIN 思路。
  4. 看接口:Postman 直接调 ScoreAnalysis 接口,看返回与耗时。
  5. 定位根因:SQL/数据/代码三层判断。
  6. 修复回归:修复后补回归用例(覆盖触发该 bug 的数据状态),防复发。

Q35. 如何保证测试覆盖率?#

答:

  1. 需求覆盖:需求文档每条都有用例对应,用追溯矩阵。
  2. 代码覆盖:核心模块(登录、成绩导入、排课)读代码做分支覆盖,补漏分支用例。
  3. 场景覆盖:用场景法覆盖真实操作路径,不只测单功能。
  4. 数据覆盖:有效/无效/边界/脏数据(NULL、空串、“null”字符串)。
  5. 回归集 + 缺陷反哺:每个修复的 bug 补一条用例进回归集。
  6. 度量:用例数 / 需求数、缺陷率、漏测率复盘改进。

Q36. 你觉得这个项目还有哪些可以改进的测试点 / 风险?#

答:

  1. 安全:JWT 密钥硬编码、GET 传密码、异常明细回显、无 token 黑名单(登出可重放)。
  2. 配置:application.yml 明文存 DB/Redis 密码、固定验证码 8888 需生产关闭。
  3. 健壮性:Excel 导入对模板格式强依赖、POI 全量加载大文件易 OOM。
  4. 并发:选课余量无锁可能超卖、排课资源抢占。
  5. 可测性:建议加接口文档(Swagger)、单元测试、日志规范,便于测试与排障。

附:高频”自我介绍 + 项目”模板#

面试官常问”讲一个你测过的印象最深的 bug”——建议用 bug1(班级下拉显示 ID): 现象首次异常再开正常 → 看似随机 → 定位到 init 方法漏调 loadClassList → 异步时序问题 → 用场景法补”冷启动”用例进回归集 → 举一反三排查所有级联下拉。这个故事完整覆盖了现象→定位→根因→测试方法→回归预防,是测试岗高分回答结构。

支持与分享

如果这篇文章对你有帮助,欢迎分享给更多人或赞助支持!

赞助
高校教务管理系统 - 软件测试岗位面试题
https://firefly.cuteleaf.cn/posts/编程学习/软件测试/面试/软件测试岗位面试题/
作者
伊月酱
发布于
2026-09-02
许可协议
CC BY-NC-SA 4.0
Profile Image of the Author
Firefly
Hello, I'm Firefly.
公告
欢迎来到我的博客!这是一则示例公告。
音乐
封面

音乐

暂未播放

0:00 0:00
暂无歌词
分类
标签
站点统计
文章
34
分类
11
标签
49
总字数
46,777
运行时长
0 天
最后活动
0 天前

文章目录