ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

软件测试基础期末复习:黑盒白盒、用例设计与缺陷管理核心考点

软件测试基础期末复习:黑盒白盒、用例设计与缺陷管理核心考点

又到了期末复习的时候。软件测试这门课,说简单也简单,说麻烦也麻烦。简单在于它不像数据结构或算法那样需要你写一堆代码,麻烦在于概念多、术语密、案例分析绕,稍不注意就把黑盒和白盒混在一起,把测试级别和测试类型搅成一锅粥。我当年期末复习的时候就犯过这个毛病,抱着教材从第一章翻到最后一章,合上书感觉什么都记住了,一到做题又模棱两可。

这篇文章就是帮你把软件测试基础练习的重点重新梳理一遍。不是照搬教材,而是按期末考试的出题习惯来拆解:哪些概念必须背、哪些计算必须会、哪些案例必须能现场设计。适合正在准备软件测试期末考试的在校同学,也适合刚入行想快速建立测试知识框架的初学者。耐心看完,配合题目练一遍,期末应该能稳不少。

1. 先摸清楚这门课到底在考什么

1.1 软件测试的目标与定义,别只会背“验证”

教材上对软件测试的定义一般都这么写:在规定条件下对程序进行操作,以发现程序错误、衡量软件质量,并对其是否满足设计要求进行评估的过程。

这句话有两个关键词容易被考试问到:验证和确认。

验证,英文叫Verification,核心问题是“我们有没有正确地构造产品”,也就是对照需求文档、设计文档,检查每一步做对没有。确认,英文叫Validation,核心问题是“我们构造的产品是不是正确的产品”,也就是最终交付的东西到底能不能满足用户的真实需求。区别在哪里?举个生活化的例子:你照着食谱做一道菜,验证是检查你有没有按食谱的步骤放调料、控制火候;确认则是这道菜端上桌,客人吃了一口说好吃,这才是确认成功。做测试不是单纯“找bug”,而是通过验证和确认两条线,为软件质量提供信心。期末选择题如果出现“软件测试的目的是什么”,千万不要选“证明程序没有错误”,正解是“发现程序中尽可能多的错误”,这个坑年年有人踩。

1.2 七条测试原则,每个都能对应一个反面场景

测试原则是期末的高频考点,经常以判断或简答形式出现。核心是这几条,每一条你都要能举出例子来说服阅卷老师你真的理解了。

测试能证明缺陷存在,但不能证明缺陷不存在,这就是第一个原则。哪怕你设计了1000条用例全都通过,也只能说明这1000条覆盖到的路径没问题,覆盖不到的地方依然可能藏着问题。测试越早介入,发现缺陷的成本越低,这一点对应软件工程里的“缺陷放大模型”:需求阶段的一个理解偏差,留到系统测试阶段可能需要花几十倍的代价去修复。所以测试不是等代码写完才开始,需求评审、设计评审阶段就要参与。

缺陷集群性、杀虫剂悖论,这两条也经常成对出现。缺陷集中在少数模块里,经验丰富的测试员会把资源倾斜到高风险区域,这就是集群性。测试用例反复使用同一批数据、同一套路径,时间久了再难发现新问题,就好像杀虫剂用多了虫子产生抗药性,所以要不断补充新的测试输入。剩余两条——测试活动依赖于测试背景、不存在缺陷不一定代表没有部署失败,前者说的是不同行业、不同场景下测试策略不一样,后者说的是就算测出来的bug全修完了,也可能因为环境配置、用户使用习惯等问题导致上线后依然不顺利。复习的时候,把每一条原则对应到一个具体的场景里记,比死背定义要牢固得多。

1.3 测试级别和测试类型,一张表分清

很多同学把测试级别和测试类型混在一起答,一考试就露馅。级别强调测试的粒度阶段,类型强调测试的目的和角度,它们是两个维度的东西。

软件测试通常分为四个级别:单元测试、集成测试、系统测试、验收测试。单元测试针对最小模块,一般由开发人员自己完成;集成测试关注模块之间的接口和交互;系统测试把整个软件系统当作整体,验证是否满足需求;验收测试由用户或代表用户的团队来做,决定软件是否可以被接受。

集成测试的策略也是简答题常客。自顶向下集成需要写桩模块,用来模拟被测模块的下层调用;自底向上集成需要写驱动模块,用来模拟上层调用;大爆炸集成一次性把模块全部组装起来,适合模块规模不大的项目;探索式或叫混合式集成,则结合了前两种的优点。

测试类型就更多了:功能测试看需求功能是否实现,性能测试看响应时间、吞吐量、资源占用,压力测试看系统在极端负载下的表现,回归测试看修改代码之后有没有把原有功能弄坏,冒烟测试则在版本提测后先快速跑一遍主流程,如果主流程都过不了,直接退回给开发,不进行详细测试。另外还有安全测试、兼容性测试、易用性测试等。复习时可以用“级别回答开发流程的阶段,类型回答测试关注的角度”这一句话来区分。

2. 黑盒测试用例设计:最容易现学现用的得分点

黑盒测试把程序看作一个不透明的黑盒子,不关心内部逻辑,只关心输入和输出。期末考试里,黑盒设计方法是大题中的绝对主力,尤其是等价类划分和边界值分析,基本属于必考内容。如果你能把这两类题完整地按步骤写出来,卷面分数至少保住三成。

2.1 等价类划分:先列有效,再找无效

等价类划分的思路是把无穷多的输入数据按是否产生相同效果分成若干类,从每类中选择有代表性的数据作为测试用例。它最重要的一个原则是:不仅要有有效等价类,还要有无效等价类。很多新手只想着测合法输入,忘了程序要能优雅地处理非法输入,结果丢分丢得莫名其妙。

拿一个典型题目来演示。假设有一个报名系统,要求输入年龄,规定年龄在1周岁到120周岁之间为合法。有效等价类是1到120之间的整数;无效等价类至少有三个:小于1的整数、大于120的整数、非数字或小数等异常输入。注意,小数虽然数字上落在1到120之间,但如果需求明确要求整数,小数就要归入无效等价类。题目没有明确说整数时,你可以先写明前提假设,这也是一种得分策略。

组织答案时,按下面这个格式写基本不会失分:

  1. 确定输入条件:年龄为1~120的整数。
  2. 划分等价类并编号:
    • 有效等价类:1~120的整数
    • 无效等价类:小于1的整数、大于120的整数、非整数(小数、字符、空值)等
  3. 为每个等价类设计一个用例,编号对应,写明输入值和预期输出。

实际考试时,题干还可能给多个输入条件,比如同时有姓名长度、邮箱格式、密码长度,你要对每个条件分别划分等价类,再组合出测试用例。组合时不需要把所有有效类做笛卡尔积全覆盖,通常取一条覆盖所有有效类的用例,再为每个无效类单独设计一条用例。这样既能验证正常流程,也能验证异常流程。

2.2 边界值分析:六个点,轻松拿下计算类题目

边界值分析是基于一个朴素又真实的经验:程序最容易在边界处出错。写代码时“<”和“<=”写混、循环的起止条件差一位,这些都是经典bug,所以测试用例必须重点覆盖边界。

还是以上面的年龄条件“1~120的整数”为例。边界是1和120,那么需要测试的典型边界值包括:上点1、120,离点0、121,有时还要针对内点取2、119。如果你学过边界值分析的“两值法”和“三值法”,简单记忆就是:上点是边界上刚好合法的点,内点是边界内侧紧邻的点,离点是边界外侧紧邻的点。对1的下边界,上点就是1,内点就是2,离点就是0;对120的上边界,上点就是120,内点就是119,离点就是121。

期末计算题里,经常出现“如果输入范围是a到b,请设计边界值测试用例”的题目。标准处理方式是:对最小值a取a-1、a、a+1三个值,对最大值b取b-1、b、b+1三个值,再加上一个正常范围内的代表值,一共7个用例,基本能覆盖边界附近的常见缺陷。如果把每个边界点的“刚好等于”和“刚刚越界”都覆盖到,那这道大题就可以拿满了。

边界值分析要配合等价类划分一起用:等价类确定测哪些类别,边界值确定每个类别里最值得测的具体数值。两个方法不是对立的,是互补的。答题时先写“采用等价类划分+边界值分析方法”,再展开具体用例,阅卷老师一看就知道你学明白了。

2.3 决策表和状态转换:两个容易被忽视的高频点

决策表法适合处理多个条件之间相互组合、不同组合对应不同动作的业务逻辑。比如登录功能,有账号存在与否、密码正确与否、账号锁定与否三个条件,每个条件有“是/否”两种取值,理论上共2的3次方等于8种组合。决策表由条件桩、动作桩、条件项和动作项组成,看起来复杂,其实画起来就是一张规规矩矩的表格。

考试中遇到这类题,建议先把条件桩和动作桩列出来,再逐步填入条件项的组合。条件过多导致组合爆炸时,可以通过合并相同动作的条件项来化简。这个方法虽然比等价类和边界值繁琐,但考察频率不低,尤其是“根据以下业务规则设计决策表”这类题,一旦掌握就是送分题。

状态转换法关注的是被测系统在不同状态之间如何迁移。比如一个订单有“待支付”“已支付”“已发货”“已取消”四种状态,事件“支付”让待支付变成已支付,“取消”可能在待支付和已支付两个状态下都允许操作,“发货”只能在已支付状态下发生,等等。考试时可能给你状态图,要你列出状态迁移表,或者反过来根据需求描述补全状态图。答题时注意区分合法迁移和非法迁移,很多题目专门考查“非法状态下操作应被拒绝”这一点。

3. 白盒测试与覆盖率:概念题和计算题的结合体

白盒测试又叫结构测试或逻辑驱动测试,测试人员需要了解程序内部结构和逻辑路径,以此为基础设计用例。期末考题一般集中在覆盖率概念、圈复杂度计算、根据流程图画独立路径这几个方面。

3.1 语句覆盖、判定覆盖、条件覆盖,三者千万别混

先看一段简单的伪代码:

输入变量a、b if (a > 1 && b < 5) c = a + b else c = a - b 输出c

语句覆盖要求每条可执行语句至少被执行一次。上面这段代码,只要执行一次if条件为真的分支,就能覆盖“c = a + b”这条语句;执行一次if条件为假的分支,就能覆盖“c = a - b”。所以设计两条用例就能达到语句覆盖。但问题在于,万一程序里有一句“if (x > 10) x = 10”藏在某个分支里,语句覆盖如果不满足执行条件,就可能漏掉。语句覆盖是最弱的标准。

判定覆盖也叫分支覆盖,要求每个判定的“真”“假”分支都至少走一次。上面代码只有一个判定,设计一条条件为真、一条条件为假的用例,就能同时满足语句覆盖和判定覆盖。但如果判定本身由多个逻辑条件组成,比如“a>1 && b<5”,判定覆盖不能保证每个子条件都取过不同值。

条件覆盖要求每个判定中的每个条件都取到真和假两种可能。对“a>1 && b<5”来说,就是要让a>1出现真和假,让b<5出现真和假。设计用例时,要分别关注a和b,而不是只看整个if的结果。再往上还有判定/条件覆盖和条件组合覆盖,条件组合覆盖要求对每个判定的所有条件组合都至少出现一次。复习时可以简单记:语句覆盖最弱,条件组合覆盖相对最强,但也不是最强中的最强,因为还有路径覆盖。

3.2 圈复杂度计算,记住三个公式就够

圈复杂度是白盒测试部分最常考的计算题,它表示程序中独立路径的数量。计算方法常用三种:

  1. V(G) = 区域数
  2. V(G) = E - N + 2,其中E是控制流图中的边数,N是节点数
  3. V(G) = P + 1,其中P是判定节点数

区域数就是控制流图把平面分成的封闭区域的个数,加上图外背景区域。画流程图时,一个顺序执行部分算一个节点,一个判定算一个节点,边的数量按箭头算。圈子不圆的同学在计算时容易数错边,我的建议是在图上用数字标好每个节点、每条边,再去套公式,别用眼睛扫一遍就填答案。

以上面的伪代码为例。它有一个if判定,流程图中判定节点引出两个分支,最后汇合。判定节点数P=1,所以V(G)=P+1=2,也就是说需要两条独立路径才能做到基本路径覆盖。如果代码里有嵌套的if,判定节点数就要逐个数清楚,嵌套内的每个if都算一个判定节点。这里有个常见的易错点:and和or连接多个条件时,如果在一个if内部,判定节点按一个算,但条件覆盖考虑的是每个独立条件各自取真取假。

3.3 独立路径与实际用例设计步骤

独立路径的概念在白盒测试里特别重要。一条独立路径至少包含一条此前路径没走过的边,基本路径集的路径数量等于圈复杂度数值。考试可能会给一小段代码或流程图,要求你列出独立路径,并设计测试用例。

操作步骤一般是:

  1. 把代码转换成控制流图,每个处理框是节点,箭头是边。
  2. 确定圈复杂度V(G)。
  3. 从起点到终点找V(G)条独立路径。
  4. 为每条路径设计一组输入,使程序实际走该路径,并写出预期输出。

还是用上面的伪代码,路径一走if为真的分支,路径二走if为假的分支。设计用例时,要给出a和b的取值,比如路径一取a=5、b=2,使a>1和b<5同时成立;路径二取a=0、b=10,使判定整体为假。写完路径后,还要简单说明预期的c值分别是7和-10。这样一套完整的白盒考试答案结构就出来了。如果题目还要求写“测试结果分析”,记得加上“执行结果与预期一致,说明该路径逻辑正确”这类结论。

4. 缺陷管理与测试文档:主观题别再空着

期末试卷里除了选择判断和用例设计,还有一类让人头疼的题目,就是简答和案例分析题:给你一段缺陷描述,让你填写缺陷报告单;或者问你缺陷从提交到关闭经历哪些阶段;又或者让你写出测试计划包含哪些要素。很多同学不是不会,而是不知道按什么结构来答,写了两三行就憋不出来。其实这类题有套路,掌握了模板就非常稳。

4.1 缺陷生命周期:从发现到关闭的完整状态流转

缺陷生命周期描述了一个bug从被测试人员发现到最后关闭或被拒绝的完整过程。标准的生命周期一般是这样:测试人员提交缺陷,状态为新建;测试负责人审核后确认是有效缺陷,将状态改为已确认,并指派给开发人员,状态变为已分配;开发人员修复完成后,状态改为已修复;测试人员在新的版本上验证修复是否生效,如果验证通过,状态改为已关闭。如果验证明明还复现,或者开发说自己修复了但测试一跑还是原样,就把状态重新置为重新打开或新建,继续跟踪。

除此之外,还有几种特殊状态:开发人员认为这不是缺陷的,可以标记为拒绝或无效;优先级不高、这版本修不完的,可以标记为推迟或延期处理;如果发现是需求理解不一致导致的,可能转到讨论阶段。考试时画状态流转图不现实,但你可以用文字加箭头把状态列出来,再补充说明“每条状态流转都有相应的触发条件”。这样答既清晰又不啰嗦。

4.2 缺陷报告的关键字段:优先级和严重性是两回事

填写缺陷报告单是经典实操题型,题干通常会给你一段bug描述,比如“在登录页面输入正确用户名和密码,点击登录按钮后无响应,浏览器控制台报500错误”。你要把这段信息拆解到不同字段里。

缺陷报告单的字段很多,但核心是这几点:缺陷编号、缺陷标题、所属模块、发现版本、发现环境、优先级、严重性、操作步骤、预期结果、实际结果、附件或截图。最容易失分的是优先级和严重性的区别。严重性衡量缺陷对软件质量的破坏程度,比如系统崩溃、数据丢失就算严重程度高,界面按钮文字错别字就算严重程度低。优先级衡量修复缺陷的紧迫程度,从业务流程是否被阻塞的角度来看。一个严重性很高但当前用户根本走不到那个功能的bug,优先级可能并不高;一个严重性很低的文案错误,如果客户马上要验收首页,优先级也会临时调高。答题时要分开写,不要混为一谈。

操作步骤一定要写清楚前置条件和复现路径。比如前置条件是“已登录用户,账号拥有管理员权限”,复现路径是“进入系统设置→点击用户管理→选择某个用户→点击删除按钮”,预期结果是“弹出二次确认对话框,确认后用户被删除”,实际结果是“点击删除按钮直接删除且无任何提示”。缺少前置条件、缺少具体路径都是扣分项。如果你是自主设计缺陷报告的题目,可以按下面这个模板来写:

缺陷标题:【功能缺陷】删除用户时缺少二次确认 所属模块:用户管理模块 环境:Windows 10 / Chrome 120 / 测试版本V1.2 严重性:中 优先级:高 操作步骤:进入用户管理页面→点击用户“A”的删除按钮 预期结果:弹出是否确认删除的对话框,点击确定后才删除 实际结果:点击后立即删除用户,无任何确认提示 备注:附加截图及抓取的接口日志

4.3 测试计划、测试用例与主观题的答题套路

测试计划是测试工作的顶层设计,包含的内容有不少:测试目标、测试范围、测试策略、资源安排、进度安排、风险与应对措施、准入标准与准出标准。在很多判断题里,会把“测试计划只需要列出测试用例”这种说法拿来考察,你需要能一眼看出这种表述的错误。测试计划关注“做什么、谁来做、什么时候做、怎么做”的层面,而测试用例关注“具体输入什么、操作什么、预期什么”的层面。

测试用例的字段通常包括用例编号、用例名称、优先级、前置条件、测试数据、操作步骤、预期结果、实际结果、测试结果。答题时设计测试用例,不要把预期结果空着,也不要写“程序正常运行”这种空话,一定要具体到“页面显示XX提示信息”“返回值为XX”“数据库记录被更新为XX状态”。阅卷老师看到具体的预期结果,才能判断你真的会设计用例,而不是在凑字数。

遇到“简述集成测试中自顶向下策略的优缺点”这类简答题,可以按“定义+过程+优缺点+适用场景”的结构回答。先用一句话说明自顶向下集成是从顶层模块开始,按控制层次逐步向下,把子模块用桩模块代替,再说明优点是能较早验证主要控制结构,缺点是桩模块成本高,底层模块错误可能较晚暴露,最后补一句适用于控制结构清晰、顶层逻辑稳定的项目。这种结构化答题法几乎能应付大多数测试理论简答题。

5. 自动化测试概念和期末冲刺的复习策略

自动化测试在期末试卷里占的比重一般不高,但一定会有那么一两道概念题,比如“什么是自动化测试”“自动化测试的优缺点”“什么场景适合自动化测试”。这些基础概念靠死记也能答,但如果能把它们串进整个测试框架里理解,答题会更有底气。

5.1 自动化测试的基本原则,理解比背答案重要

自动化测试本质上是把人为操作的测试活动转化为由工具或脚本自动执行的过程。它的核心价值不是替代手工测试,而是解放测试人员重复劳动,同时提升回归测试的效率。所以那些一次性需求、界面尚未稳定的模块,不适合大手笔做自动化;而频繁回归、功能稳定、执行步骤重复度高的场景,比如登录、注册、订单主流程等,就比较适合自动化。

考试常考的点是自动化测试的优缺点。优点可以从效率、一致性、覆盖率、资源消耗几个角度展开:脚本执行速度快,凌晨也能跑全量回归;重复操作每次都按相同脚本执行,避免人为主观差异;脚本能覆盖手工很难执行的庞大用例集;同时解放人力资源去关注探索性测试。缺点是开发维护脚本的成本高,需求变更后脚本需要跟着改,对测试人员的编程能力也有要求,再加上自动化工具或框架本身的引入成本,小型项目可能得不偿失。回答优缺点时,能给出“什么场景该用、什么场景不该用”的分析,得分就会更高。

5.2 期末冲刺怎么安排:别把时间耗在低效抄写上

到了临近考试,光靠从头翻教材效率太低。我个人比较推荐按知识点分组刷题,把每一章最核心的概念做成自测卡片来记忆。比如看到“等价类划分”,你心里要能马上说出它的步骤和适用场景;看到“缺陷”,要能立刻说出生命周期各状态和缺陷报告单的关键字段。说不出来,就优先巩固这个点,而不是拿起一套题从头刷到尾。

另一个高效方法是用“穿线法”把分散的知识串起来。比如给你一个登录模块,你可以从需求评审、设计测试用例、执行测试、记录缺陷、回归验证到最终输出测试报告,完整走一遍流程,把课程里几乎所有知识都融进去。需求阶段先分析输入条件和业务规则,用等价类边界值设计用例;测试执行阶段记录实际结果与预期不符的地方;缺陷管理阶段填写缺陷单并跟踪生命周期;缺陷修复后做回归,决定整个模块是否可以进入验收。这个练习如果能在考试前做两遍,比背十遍章节框架都管用。

5.3 一道综合题的自查式解法

最后分享一个自查思路,适用于各种综合设计题。拿到题目后,不要急着下笔,先自问三个问题:

  1. 题目给出的是需求规格还是实现代码?需求规格用黑盒方法,实现代码用白盒方法。
  2. 输入空间是连续范围、离散集合还是条件组合?连续范围用边界值+等价类,离散集合枚举等价类,多条件组合考虑决策表。
  3. 答题时需要包含前置条件、具体输入、操作步骤和预期结果吗?只要题目说“设计测试用例”,这四要素就都别落下。

按这个思路走,即使题目背景陌生,也不会出现思路跑偏的情况。我见过有同学拿到综合题,第一反应是回忆教材原文,结果花了十分钟背了一段不相关概念,最后连用例都没设计完。正确姿势是先判断题型和出题意图,再动手写,得分效率会高很多。

6. 一些实战中踩过的坑和复习建议

第一,不要过度依赖所谓“题库”。某个知识点的题目确实见过,原题再现的概率也有,但一旦换个场景、换个数据,死记答案的人就会露馅。比如等价类划分题目从“年龄1到120”换成“成绩0到150”或“金额100到5000”,核心做法完全一样,就看你会不会迁移。理解规则,永远比记住答案可靠。

第二,做计算题一定要看清判定条件。圈复杂度计算的流程图中,如果判断条件是复合条件,比如“A and B”“A or B”,数判定节点时是按一个判定节点来算的。但如果题目明确要求按条件组合覆盖设计用例,就需要把A和B分别列出来。审题这一步,往往就拉开了一大批人的分数。

第三,考前不要只背名词解释。软件测试的期末卷子,名词解释比重不大,应用分析才是大头。哪怕你把“回归测试”的定义背得滚瓜烂熟,碰到“版本更新后应该优先执行哪种测试”的选择题,还是要能瞬间反应过来是回归测试。概念记住意思和应用场景,比逐字背诵更有用。

第四,读题目时把关键词圈出来。看到“从用户角度”“不考虑内部结构”就圈出来对应黑盒,看到“覆盖”“路径”“分支”就对应白盒,看到“止损”“退出标准”就对应测试计划或缺陷管理。这些关键词是答题的指路牌,能帮你快速锁定知识模块。

写到这里,软件测试基础练习的重点基本过了一遍。说实话,这门课的知识量不算大,难的是把概念和应用真正对应起来。期末复习阶段,与其焦虑地翻书,不如动手把典型题目按“审题—选方法—写用例—给结论”的流程练一遍。练得多了就会发现,试卷上的题目再怎么变,也逃不出等价类、边界值、判定覆盖、缺陷生命周期这些核心话题。祝你复习顺利,考试稳过。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进