首页 / 资讯中心 / 文章详情

在线考试系统测试分析报告:用例设计、压测与缺陷分析

在线考试系统测试分析报告:用例设计、压测与缺陷分析 ★ FEATURED ARTICLE
在线考试系统的测试报告最容易写成一份看起来很全、用起来没用的文档。我经手过几个模拟项目的考试类系统最典型的一次是考问通系统上线前的测试分析报告团队把用例执行率刷到98%缺陷关闭率写得很漂亮结果正式考试当天中午两个考场的考生集中反馈答题卡勾选后刷新就没了。这份考问通系统测试分析报告后来重写了三遍才敢交付也正是那一次让我彻底改变了对测试报告这件事的理解:它不是给流程交差的凭证而是把这个系统在什么条件下会坏、坏到什么程度、坏了以后谁来兜底一次性讲清楚的说明书。这篇内容适合正在做教育类、测评类系统测试的同学也适合需要评审测试报告的开发、产品和技术负责人我会把用例怎么设计、压测怎么估、缺陷怎么分析、结论怎么写这四件事拆开讲透每一步都给出为什么这么做的理由。1. 考问通系统这类项目测试报告的读者到底是谁很多测试同学写报告的默认读者是验收的人于是全篇都在证明我干了很多活:执行了多少条用例、发现了多少个缺陷、修复率多少。这种写法在流程上无懈可击但对真正要用这份文档的人几乎没有价值。想清楚读者是谁报告的骨架自然就变了。1.1 第一读者其实是三个月后接手的人考试类系统有个特点:使用频率极低但每次使用都是高压场景。一个学期可能就期中、期末两次集中使用中间几个月没人碰。等到下一次考试前接手的人打开这份报告他最想知道的不是你当时跑了多少条用例而是这个系统在什么情况下会出问题、上次出事的地方在哪、我这次要注意什么。所以我后来写报告会强制自己在开头加一段本轮测试的边界说明明确写出:测了什么版本、测了哪些模块、哪些模块没测或只做了冒烟、测试环境的机器配置和真实考场差多少。这段话看起来是在自我设限实际上是给后来者画了一张地图。比如我会写本轮未覆盖主观题双评仲裁流程该模块仅在预发布环境做了单条正向用例验证多评冲突场景未验证。接手的人一看就知道这块是个雷区下次动它之前得先补测。这个习惯是从一次事故里长出来的。当时有个模拟项目上一轮测试报告里写着阅卷模块测试通过下一轮的人就默认这块安全直接改了分数合成的逻辑结果多评取平均的权重算错了导致一批成绩偏低。翻回原始报告才发现所谓的测试通过其实只跑了两条用例连多评场景都没构造。通过这两个字如果没有范围限定就是一颗定时炸弹。1.2 一份报告必须正面回答的四个问题我把测试分析报告要回答的问题收敛成四个缺一个都算不合格:问题对应报告章节判断合格的标准这个系统现在能不能上测试结论有明确的通过/有条件通过/不通过且给出条件上了以后最可能在哪里出事风险与遗留缺陷每条风险有触发条件和影响面出事以后怎么快速定位缺陷分析与环境说明关键链路有日志点位、有复现步骤下一轮测试该往哪使劲覆盖度分析与建议指出未覆盖区域和优先级这四个问题里第一个最容易写第四个最难写。因为第四个要求你诚实承认自己没测到什么。很多团队不愿意写怕被追责结果就是下一轮重复踩同一个坑。我的做法是把未覆盖和建议下一轮优先覆盖放在一起写语气从我没做变成建议优先做既保留了信息也不会变成甩锅。顺带说一个实操细节:报告的目录结构和这四个问题对齐之后评审会上的提问会明显变少。因为大部分人翻报告就是带着这四个问题来的你直接把答案放在他顺手的路径上讨论就能聚焦在真正的分歧点上而不是花半小时问你们到底测没测交卷。2. 用例设计:把考试公平翻译成机器能判定的断言考试系统和普通业务系统最大的区别在于它的核心诉求是公平。公平是个很虚的词测试的价值就在于把它拆成一条条能判定的断言。这一块如果偷懒后面的缺陷分析全是空的。2.1 组卷与抽题:用覆盖度矩阵代替随机抽几套看看考问通系统的组卷逻辑通常支持按知识点、按题型、按难度配比抽题。测试新手最容易犯的错是:手动组几套卷子看看题目数量对不对、总分对不对就认为测完了。这样测的问题是随机算法的分布偏差根本暴露不出来。我的做法是构造一个覆盖度矩阵把抽题结果当数据分析。具体操作是写一个小脚本调用组卷接口一千次记录每次抽出的题目 ID 集合然后统计三类指标:知识点覆盖率:每个知识点被抽中的次数 / 总组卷次数理论值应该接近配置比例偏差超过 ±5% 就要查是不是权重实现有问题;重复率:同一考生连续两次组卷的重题比例如果配置了不重复抽题策略这个值必须是 0;难题占比:实际抽出的难题数量 / 配置的难题数量看难度分层是否生效。# 组卷覆盖度抽样统计示意 from collections import Counter def check_paper_distribution(api, rounds1000): kp_counter Counter() diff_counter Counter() for _ in range(rounds): paper api.generate_paper(exam_iddemo) for q in paper[questions]: kp_counter[q[knowledge_point]] 1 diff_counter[q[difficulty]] 1 total sum(kp_counter.values()) return {k: round(v / total, 4) for k, v in kp_counter.items()}这段代码没什么技术含量但它能抓出一类靠手工点页面永远发现不了的问题:某个知识点的权重配置在代码里被写成了固定值配置项根本没生效。我在一个模拟项目里就是这么发现易错题优先这个开关是死的——连抽一千套易错题的占比和普通题完全一致。还有一个坑要提:抽题接口在并发组卷时可能出现超卖。比如题库里某知识点只有 20 道题同时有 50 个考生在组卷如果实现是先查后取就会出现同一道题被分给多个考生或者抽取时题库已被扣空导致组卷失败返回空卷。测试时要用 20 到 50 的并发去打组卷接口观察返回失败率和重题率。这个场景在开考前集中组卷的几分钟里是必然发生的。2.2 计时、暂存、断线续考:边界用例的穷举与裁剪考试过程这块边界条件特别多而且每一条都直接对应真实的考生投诉。我一般按时间轴 × 状态的方式来穷举先列状态再列转换条件。关键状态包括:未开考、已开考未答题、答题中、已暂存、已交卷、超时自动交卷、断线离线中、重连恢复中。关键条件包括:开考前 1 秒进入、开考瞬间进入、剩余时间 1 秒交卷、剩余 0 秒自动交卷、答题过程中断网 10 秒/1 分钟/5 分钟、断网期间跨过考试结束时间。这里有个必须验证的点:自动交卷和手动交卷的竞态。考生在最后几秒点交卷同时服务端的定时任务也触发了自动交卷如果两边的处理没有做幂等就会出现交卷两次、答案被覆盖或者成绩重复计算。测试方法很简单把考试时长设成 30 秒在倒计时剩 1 秒时脚本调用交卷接口重复 100 次看是否出现重复的提交记录。再一个高频问题是答案暂存的落库时机。很多实现是前端定时 5 秒往服务端同步一次网络抖动时就会丢最后一次修改。上一段开头提到的那次勾选刷新就没了根因就在这里:前端在选项变化时只更新了本地状态没触发同步而同步定时器又因为页面切换被重置了。这类问题的测试方法是:改答案后立刻断网、恢复、刷新连续验证十轮看是否有丢失。用自动化脚本来做比手动靠谱得多因为手动操作的时间间隔往往太宽容刚好错过了那个窗口。2.3 判分链路的判定表设计判分是考试系统里最不能出错、也最难测全的模块。客观题自动判分相对简单但一旦涉及多选题漏选给半分、判断题答错倒扣、主观题多评取均值组合就多了。这种情况用判定表最省事。以多选题为例把条件列出来:是否全选对、是否漏选、是否错选、是否有半分规则、是否倒扣。组合起来就是一张表每一行对应一条用例和期望分。表格一摆出来产品和开发往往会发现规则本身就有歧义——比如漏选给半分和错选零分同时触发时怎么算配置项里根本没写清楚。判定表的最大价值不是测出 bug而是在测试阶段把规则歧义逼出来。主观题的多评链路要单独测。核心是分数合成:两个评卷人分差在阈值内取平均超过阈值进仲裁仲裁后以仲裁分为准。测试要点是阈值的边界值比如阈值设 2 分那分差正好 2 分时走哪条路、2.01 分时走哪条路,必须一一验证。我见过把写成的情况结果大量本该直接取平均的卷子被送进仲裁阅卷量翻了一倍。3. 压测:考场并发和普通业务并发是两个物种普通业务的流量是平滑的考试系统的流量是脉冲式的:开考那一分钟、交卷前五分钟、考试结束那一刻三个尖峰顶上去平时几乎为零。按平均值做容量规划一定会出事。3.1 从报名人数推算峰值比拍脑袋定并发靠谱压测第一步不是写脚本是算数。我的推算是这样的:假设某场考试报名 3000 人开考时间统一考生会在开考前 5 分钟到开考后 1 分钟内陆续进入这 6 分钟里 80% 的人会完成进入动作也就是 2400 次进入分摊在 360 秒平均 6.7 次/秒。但这不是峰值因为大家习惯在整点前 30 秒集中点进入考场实际峰值可能是平均值的 5 到 8 倍,按 40 到 55 次/秒估。交卷的峰值更陡。假设考试时长 90 分钟允许提前交卷那么提前交卷的人集中在最后 10 分钟加上时间到的强制自动交卷最后 1 分钟可能有 30% 的人同时提交也就是 900 次提交在 60 秒内完成平均 15 次/秒峰值按 3 倍算是 45 次/秒。这些数字算出来之后压测的目标就明确了:不是测 1000 并发而是进入接口扛住 55 次/秒、交卷接口扛住 45 次/秒且 P95 响应时间在 1 秒以内。目标越具体压测结果越能直接支撑结论。场景估算并发目标 TPS关注指标考生进入考场500 在线55P95 响应、错误率答题页轮询/心跳3000 在线300连接数、内存交卷提交900 集中45P99 响应、写库成功率成绩查询600 集中80缓存命中率3.2 压测脚本里最容易造假的三个地方压测结果不可信八成是脚本作弊了。我踩过三个典型:第一登录态复用不当。脚本里所有虚拟用户共用同一个 token服务端如果有基于 token 的限流或缓存压力就被这层缓存吃掉了真实场景下每个考生一个会话压力会明显不同。正确做法是预先生成 N 个真实账号的会话压测时轮询使用。第二思考时间设成 0。脚本连发请求把服务端打成了纯接口压测而真实考生答题时有几十秒的思考。压测时思考时间不是越小越好要按真实行为设:答题请求间隔 30 到 90 秒随机交卷请求前有短暂停顿。否则测出来的瓶颈位置和真实情况完全对不上。第三数据不落库。有些脚本为了跑高分交卷接口传的是空答案或者重复的考生 ID服务端走了快速失败分支压力根本没到写库这一层。压测脚本必须构造完整报文:真实的考生 ID、真实的题目 ID、完整的答案结构确保请求能走完全链路。# 压测前的数据准备生成独立考生会话示意 for i in $(seq 1 3000); do curl -s -X POST $BASE/api/login \ -d userstu_$ipasstest_only sessions.jsonl done # 校验会话有效性剔除失败项避免压测时大量 401 干扰结果 wc -l sessions.jsonl3.3 瓶颈定位:按什么顺序看指标压测跑出高延迟别急着加机器。我固定按这个顺序看:先看应用层的线程池和连接池是否打满再看数据库的慢查询和锁等待最后看缓存命中率和网络。这个顺序的原因是绝大多数的高并发扛不住最后都落在连接池和慢 SQL 上而不是 CPU。有一次模拟项目的压测TPS 卡在 60 上不去CPU 才 30%。查下来是数据库连接池配了 20而应用有 8 个实例每个实例 20 个连接加起来的并发写远超数据库能承受的量大量请求在等连接。把连接池调到 10、把交卷的写操作改成异步队列削峰之后TPS 直接上到 120。这个案例说明一个道理:压测指标里 CPU 不高不代表没问题连接池等待时间往往才是真相。4. 缺陷分析:报告里最值钱的不是通过率通过率是个给流程看的数字缺陷分析才是给决策看的内容。同一批缺陷按不同维度切能看出完全不同的结论。4.1 缺陷分布怎么统计才有决策价值至少要切三个维度:按模块、按严重度、按发现阶段。按模块看哪里最容易坏按严重度看质量水位按发现阶段看测试是否有效。模块致命严重一般轻微合计组卷抽题025310答题与暂存148619交卷提交234211判分合成136414成绩查询014510权限与后台023712这张表摆出来结论就很清楚了:答题与暂存模块缺陷最多交卷与判分模块致命缺陷最多这两个模块必须在下一轮做重点回归而且上线前要安排专项验证。如果只看总数 76 个、修复率 92%这些信息全被抹掉了。还有一个维度常被忽略:缺陷的发现阶段分布。如果 80% 的缺陷是系统测试阶段发现的单元测试和接口测试阶段几乎没产出说明前两道防线形同虚设后续迭代的质量风险会很高。这个结论写进报告比写测试充分有说服力得多。4.2 一条缺陷的完整复现链路:答题卡状态不同步我拿前面提到的那个真实影响最大的缺陷做完整复盘因为它的排查路径很典型可以复用。现象:考生在答题页勾选选项页面显示已选但刷新或切换题目再回来勾选丢失。复现概率约 1/20手动几乎抓不到。第一步确认是前端还是后端问题。在浏览器里看网络请求发现选项变化时并没有发出任何请求只有每 5 秒的定时心跳请求。说明前端没有把变更推到服务端问题在前端或前后端约定这一层。第二步看定时心跳的代码逻辑。心跳里携带的是当前题目的答案快照快照来源是组件内部的answers状态。到这里发现关键点:切换题目时会重新初始化组件answers被重置成服务端返回的数据如果此时心跳还没发出去本地修改就丢了。第三步构造稳定复现。把心跳间隔改大测试环境可配在选项变化后 4 秒内切换题目稳定复现。同时发现另一个关联问题:如果考生在 4 秒内连续切换三道题三份修改会一起丢。第四步修复方案讨论。开发最初想改成选项变化立即发请求但这样每点一次就一个请求3000 人同时答题时请求量会翻几十倍心跳机制的意义就没了。最终方案是选项变化时本地打脏标记并立即触发一次延迟 800 毫秒的同步防抖同时页面卸载和切题时强制同步一次。这个方案兼顾了请求量和可靠性。第五步回归验证。用自动化脚本模拟改答案→800 毫秒内切题→刷新跑 200 次丢失率为 0再模拟弱网延迟 300 毫秒、丢包 5%跑 200 次丢失率 0.5%看日志确认是重试机制补上的可接受。这条链路的经验是:**低概率问题的排查靠的不是反复手点而是先把理论上的时序画出来找出那个窗口然后人为放大窗口去复现。**时间相关的缺陷一定要找可控的时间参数比如心跳间隔、超时阈值改它。4.3 遗留缺陷的风险描述怎么写才不算甩锅上线前一定会有遗留缺陷关键是描述方式。我要求每条遗留缺陷必须写清三件事:触发条件、影响范围、临时规避方案。缺一条就是不合格。反面例子:偶现答题卡不同步概率低建议上线后观察。这话等于什么也没说。正面写法是:在选项修改后 1 秒内切换题目时约 5% 的概率丢失本次修改影响范围为本场考试的所有考生影响结果是该题记零分。规避方案:监考端提示考生修改答案后停留 2 秒再切题同时后台开启答题记录审计考后可人工核对异常零分记录。这两种写法在评审会上的待遇完全不同。后者会引发要不要在上线前修的真实讨论前者只会引来一句那就观察吧然后真的出事。5. 兼容性与弱网:实验室环境永远比真实考场温柔测试环境的网络是机房内网设备是新款笔记本考场环境是学校机房的旧机器加共享带宽。这中间的差距必须在报告里量化出来否则结论就是空中楼阁。5.1 设备矩阵的取舍逻辑考试类系统的设备矩阵理论上应该按真实终端的用户占比来选但测试资源有限必须取舍。我的选择逻辑是:优先覆盖占比高和性能差这两个交集。按占比排序浏览器内核主要就两三类覆盖这三类能拿住 90% 以上的人。但真正出问题的是性能差的那一端:低配机器、小内存、老版本内核。这些机器上暴露的问题往往是渲染卡顿、长列表滚动丢帧、大题干图片加载不出来PC 端测试机上完全看不出来。具体做法是准备一台低配虚拟机限制 2 核 4G 内存用浏览器开发者工具把 CPU 降速 4 倍、网络限到 3G 水平作为最差环境的基准。所有核心流程在这个环境下跑一遍能过基本就稳了。有一个细节值得单独测:题干里的富文本和公式渲染。考试题目经常包含图片、公式、表格这些内容在不同内核上的渲染差异很大尤其是公式某些渲染库在旧内核上会直接白屏。测试时要专门准备一套包含复杂题干的卷子在设备矩阵上逐台验证。5.2 弱网参数怎么设观测什么指标弱网测试的参数我一般设三档覆盖从能用到极限的情况:档位延迟丢包带宽模拟场景轻度150ms1%2Mbps家庭宽带一般状态中度400ms3%1Mbps多人共享、信号一般重度1000ms8%512Kbps考场网络拥塞观测指标不能只看页面能不能打开要看这几个:答题操作的响应延迟点选项到界面反馈、答案同步成功率、断线后的重连耗时、重连后答案完整性。其中答案完整性是最关键的方法是在弱网下做 50 次改答案→切题→回来的操作逐条核对服务端记录和本地显示是否一致。这里有个实践教训:弱网下的重连逻辑很多实现是重连成功后整页刷新看起来干净但如果考生正在填一道主观题刷新就等于清空。测试时必须专门验证主观题输入过程中断网重连看草稿有没有保住。6. 报告正文的组织:把一堆数据讲成一个结论前面所有的测试动作最后都要收敛到一份文档里。结构没组织的报告读的人要在数据里自己找结论等于白做。6.1 骨架与每章必须回答的问题我的骨架是这样的每章只回答一个问题不贪多:测试概况:这轮测的是什么、什么环境、什么范围。回答这份报告的适用边界在哪。测试策略与用例设计:为什么这么测重点在哪。回答为什么可信。执行结果:用例执行数据、缺陷数据。回答测出了什么。缺陷分析:分布、典型缺陷、根因。回答问题集中在哪。性能与兼容性:压测数据、弱网表现。回答扛不扛得住。风险评估与结论:遗留问题、上线建议。回答能不能上。这个骨架和前面说的四个问题是对齐的。写的时候有个小技巧:每章开头先用两三句话把结论亮出来再放数据。评审的人时间有限先看结论有兴趣再往下翻数据。这比先堆数据最后给结论的写法阅读效率高一个量级。6.2 上线结论的三种写法及其代价结论只允许三种:通过、有条件通过、不通过。三种写法对应的责任是不一样的必须想清楚再写。**通过**意味着你认为当前质量可以支撑正式使用。写下这两个字就要承担出事时无法用报告里提过风险来解释的后果。只有致命和严重缺陷全部关闭、遗留缺陷都是轻微级别、性能指标全部达标时才能写。**有条件通过**是最常用的但必须把条件写具体。不能写修复主要缺陷后上线要写交卷幂等问题修复并回归通过后上线回归用例至少包含并发重复提交 100 次、跨零点交卷 20 次。条件不具体等于给自己留了一个模糊地带出事时说不清。**不通过**在考试类项目里并不罕见尤其是第一轮。写这个结论需要的不是勇气而是把为什么不能上拆成可修复的清单。我见过一份报告写系统稳定性不足不建议上线然后开发完全不知道该改什么白白浪费一周。正确写法是列出阻断项:交卷接口在 45 TPS 下错误率 12%超过 1% 的可接受阈值需优化后重测。7. 一些踩过之后才明白的细节最后说几个报告之外的东西都是实际操作里碰出来的。测试数据要专门造一批脏数据。真实题库里有超长题干、有格式错乱的富文本、有重复的题目。测试时如果只用干净的样例数据上线后第一份导入的真实题库就可能出问题。我的做法是准备一份脏题库包含 200 道各种异常格式的题目导入后跑一遍组卷和答题能过基本就稳了。时间相关的测试一定要能改系统时间。跨零点交卷、考试跨天、时区切换这些问题只有在时钟被拨动时才会暴露。测试环境必须留一个可以调整服务端时间的开关否则这类场景根本没法测。我遇到过一次跨零点自动交卷的定时任务没触发原因是任务调度用的是自然日切分跨天后任务被重置了正是因为能改时间才测出来。报告里的截图和日志要能长期访问。缺陷截图放在临时目录三个月后打不开这条缺陷记录就等于废了。建议把关键证据统一放到固定的文档空间报告里只放链接和编号编号规则和缺陷单号对齐方便追溯。回归范围要写进报告不要口头说。哪条缺陷修复后回归了哪些用例、结果如何写成一栏表格比在群里说一句已回归通过有用得多。这块后来我们固定成一个模板每轮填一次效率反而更高因为不用每次想这次该回归什么。我个人在实际操作中的体会是测试分析报告的价值不在于它多厚而在于它有没有把未知变成已知的未知。一个系统最危险的状态不是有很多缺陷而是没人知道哪里有缺陷。把没测到的、测了但不充分的、测充分但仍有疑虑的一条一条写清楚这份报告才算真正交出去了。
阅读完成 · 觉得有帮助?
咨询建站