news 2026/10/1 11:33:16

软件测试习题精讲:白盒覆盖、等价类划分与环路复杂度

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
软件测试习题精讲:白盒覆盖、等价类划分与环路复杂度

软件工程这门课,软件测试这一章基本是所有人绕不过去的一道坎。它不像需求分析、概要设计那种偏概念的章节,背一背就能混过去——软件测试的习题,尤其是白盒覆盖、等价类划分、边界值分析、控制流图与环路复杂度这几类,是真的要动手算、动笔画,算错一步整道题的分就没了。我前后整理过不少软件工程习题和配套的参考答案,也和准备软件测试实习面试、参加全国大学生软件测试大赛的同学聊过,发现大家在这一章卡壳的地方高度集中:概念分不清、覆盖标准搞混、测试用例凭感觉写、环路复杂度算错。这篇就把软件测试章节的习题体系整个拆开,从考点分布、易混概念、典型题的完整解题过程,到参考答案该怎么用、错题怎么复盘,尽量讲透。不管你是软件工程导论期末抱佛脚,还是准备软件测试岗的笔试八股,都能直接拿去用。

1. 软件测试章节的考点地图:先搞清楚会考哪些题

1.1 软件工程教材里这一章的固定考点清单

不管你用的是吕云翔版、张海藩版还是其他主流教材,软件测试这一章的知识骨架其实非常固定,翻来覆去就这五块内容。第一块是测试基础概念,包括软件测试的定义、目的、基本原则,还有测试与调试的区别,这类属于必须死记的保分点。第二块是测试方法分类,黑盒、白盒、灰盒,各自的适用场景、优缺点、典型方法归属。第三块是测试级别,单元测试、集成测试、系统测试、验收测试,以及配套的V模型、W模型和增量式集成策略(自顶向下、自底向上、三明治)。第四块是测试用例设计方法,这也是出大题的地方:黑盒这边有等价类划分、边界值分析、判定表、因果图、错误推测、场景法;白盒这边有逻辑覆盖的六种标准、基本路径测试、控制流图、环路复杂度。第五块是面向对象测试、测试管理和测试策略这类偏理论的内容,一般以简答或选择形式出现。

1.2 不同题型的出题概率与分值分布

我把常见的软件测试习题按题型、出现频率和分值整理成一张表,你复习的时候可以按这张表分配精力,别在低分题上耗太久,也别把拉分的大题给漏了。

题型典型问法出现频率平均分值难度
选择题/填空概念辨析、原则判断高2-4分低
简答题简述测试原则、测试与调试区别高5-8分低中
用例设计题给定功能,用等价类/边界值设计用例中高10-15分中
白盒覆盖题给定程序段,设计各覆盖标准的用例高12-20分高
控制流图与环路复杂度画控制流图、计算V(G)中8-12分中高
判定表/因果图给定业务逻辑,画判定表并生成用例中8-12分中

从这张表能看出来一件事:白盒覆盖和用例设计是真正的拉分点,占的分值大、难度高,是决定你能不能拿高分的关键;而选择和简答是保分点,答不上来纯粹是没背。复习策略上,简答和选择保证不丢分,然后用大量时间练白盒覆盖和黑盒用例设计这两块。

1.3 课程习题和软件测试面试八股的重合地带

很多人以为课程习题只是为考试服务,其实软件测试这一章的习题和面试八股重合度极高。面试里高频出现的"黑盒和白盒的区别""等价类划分和边界值分析怎么用""测试流程是什么""测试用例包含哪些要素""单元测试和集成测试的区别""缺陷的生命周期",几乎全部能从教材这一章直接找到答案。也就是说,你把这一章的习题吃透,等于顺手把软件测试岗的笔试基础题也过了一遍。我自己当年就是因为把白盒覆盖的几道经典题推得滚瓜烂熟,面试时被问到"语句覆盖和判定覆盖的区别"时张口就来,细节都能说清楚,这种熟练度是临时突击背概念给不了的。

2. 先把易混概念理清楚,否则做题全是坑

2.1 测试与调试:名字像,本质完全不同

这是简答题的常客,也是很多人答得很单薄的地方。大部分人只会写"测试是发现错误,调试是改正错误",这么答只能拿到一半的分。要按维度展开才能拿满,我习惯用一张对比表来记:

维度软件测试程序调试
目的发现错误定位并修正错误
参与者测试人员或独立测试团队一般是开发人员自己
时间点贯穿整个软件生命周期通常在测试发现缺陷之后
方法有计划、有设计好的测试用例靠经验、推理、逐层排查
结果输出缺陷清单输出修正后的程序
出发点从"证明程序有错"出发从"修复已发现的错误"出发

一句话概括二者的关系:测试是"找出问题",调试是"解决问题"。测试可以发现错误,但发现错误之后的定位和修正属于调试的范畴。答题时把这几个维度分点写出来,阅卷老师一眼就能看出你是真懂了。

2.2 验证与确认:一个问"做得对不对",一个问"做的是不是对的东西"

Verification(验证)和Validation(确认)这对概念,英文教材里问得特别多,中文教材也经常考。记忆口诀很简单:验证看过程,确认看结果;验证查规范,确认查需求。

具体来说,验证回答的是"我们是不是正确地构建了产品"(Are we building the product right),检查开发过程是否符合规范、设计是否和需求一致,手段包括评审、静态分析、走查。确认回答的是"我们构建的是不是正确的产品"(Are we building the right product),检查最终产品是否符合用户真实需求,手段主要是系统测试和验收测试。我见过很多同学把这两个名字对调着写,其实只要抓住"验证对内部规范、确认对用户需求"这条线,就不会混。

2.3 错误、缺陷、故障、失效四兄弟

这一组概念在各版本教材里用词不太统一,是最容易翻车的地方。一般的关系链是这样的:人犯了错误(Error/Mistake),这个错误被写进代码或文档就形成了缺陷(Defect/Bug),缺陷在被触发时表现为系统内部的异常状态即故障(Fault),故障在运行中向外部暴露出来就成了失效(Failure)。

链路记住:人犯错→引入缺陷→运行触发故障→对外表现为失效。要特别提醒一点,国内不同教材对Fault和Defect的翻译不完全一样,有的把Fault译成"故障",有的译成"缺陷",考试时一定以你手上那本教材为准。这个坑我踩过,模拟考和期末考的参考答案对同一个词解释不同,白丢了几分。

2.4 黑盒、白盒、灰盒的选择逻辑

这三种方法的选择不是凭喜好,而是看你能不能看到内部结构、测到什么粒度。整理成表更清楚:

类型是否看内部结构测试依据适用阶段常见方法
黑盒不看需求/规格说明系统、验收等价类、边界值、判定表、因果图、场景法
白盒看代码/内部逻辑单元逻辑覆盖、基本路径、循环测试
灰盒部分看结构+功能集成接口测试、数据库测试

选择逻辑一句话:有源码且要测细粒度逻辑就用白盒,只关注功能表现就用黑盒,需要兼顾两者就用灰盒。实际项目中这三者不是互斥的,而是互补的——单元阶段以白盒为主,系统阶段以黑盒为主,集成阶段往往灰盒更好用。

3. 典型习题的完整解题过程

3.1 白盒覆盖习题:六种覆盖标准一次算清

这是最经典的软件测试大题。给定一段带两个判定的程序,要求分别用语句覆盖、判定覆盖、条件覆盖、判定/条件覆盖、条件组合覆盖、路径覆盖设计测试用例,并说明最少用例数。我拿一道教材高频题完整走一遍。

程序段如下(伪代码,实际考试里可能是C或Pascal):

void sample(int a, int b, float x) { if (a > 1 && b == 0) { x = x / a; } if (a == 2 || x > 1) { x = x + 1; } }

第一步,拆条件和判定。判定P1 = (a>1) && (b==0),内部含两个条件:c1为a>1,c2为b==0。判定P2 = (a==2) || (x>1),内部含两个条件:c3为a==2,c4为x>1。这里有个极其关键的细节:第一个if可能会修改x的值,所以设计第二个判定的用例时,x要用它当时的值来判断,而不是初始值。很多人就死在这个细节上。

语句覆盖:让两条赋值语句都执行到。取a=2, b=0, x=4,P1 = (2>1)&&(0==0)为真,执行x=4/2=2;此时P2 = (2==2)||... 为真,执行x=2+1=3。两条语句都跑到了,最少1个用例。

判定覆盖:P1真假、P2真假都要取到。用例1取a=2, b=0, x=4,P1真、P2真;用例2取a=1, b=1, x=1,P1假(a>1不成立)、P2假(a==2不成立且x>1不成立)。两个用例搞定。

条件覆盖:c1、c2、c3、c4每个条件都取真取假。还是上面两个用例:用例1里c1真、c2真、c3真、c4真;用例2里a=1、b=1、x=1,c1假、c2假、c3假、c4假。四个条件都取到了真和假,也是两个用例。

判定/条件覆盖:同时满足判定覆盖和条件覆盖,上面两个用例正好同时满足,用例数不变。

条件组合覆盖:这个要用心。P1的条件组合有TT、TF、FT、FF四种,P2的条件组合也有四种。设计如下:

用例abx初值c1c2c3c4说明
1204真真真真P1的TT,P2的TT
2211真假真假P1的TF,P2的TF
3103假真假真P1的FT,P2的FT
4111假假假假P1的FF,P2的FF

用例3里要注意,a=1导致P1为假,x保持3不变,进入P2时c3为假(a不等于2)、c4为真(3>1),对应P2的FT组合,没问题。四个用例覆盖了全部条件组合。

路径覆盖:两个判定,控制流图理论上有四条路径。TT取a=2, b=0, x=4;TF要P1真且P2假,取a=3, b=0, x=2,P1真后x变为2/3约0.67,P2中a不等于2且0.67不大于1,为假,正确;FT取a=1, b=0, x=3,P1假、P2真;FF取a=1, b=1, x=1,P1假、P2假。四个用例覆盖全部路径。

注意:条件组合覆盖和路径覆盖不是一回事,条件组合关注每个判定的条件取值组合,路径覆盖关注整体执行路径。有些题会问"哪个覆盖标准最强",答案是路径覆盖通常最强,但条件组合覆盖在某些场景下能覆盖到路径覆盖覆盖不到的组合。

3.2 黑盒测试习题:等价类划分与边界值分析的组合拳

黑盒用例设计题最经典的载体是三角形判定、日期计算、成绩等级转换、登录校验这几类。我以"三角形判定"为例讲完整流程。题目通常是:输入三条边a、b、c,判断是等边、等腰、普通三角形还是非三角形,用等价类划分和边界值分析设计测试用例。

先做等价类划分。有效等价类要考虑:能构成三角形(任意两边之和大于第三边)、且分为等边(三边相等)、等腰(两边相等)、普通三角形三类。无效等价类要考虑:某边为0或负数、两边之和等于第三边(退化成一条线)、两边之和小于第三边。划分时一个原则是"同一类里任一数据对结果的作用相同",这样每类取一个代表就够了。

再做边界值分析。三角形的边界在于"两边之和等于第三边"这个临界点,所以要在a+b=c的附近取值,包括a+b=c-1、a+b=c、a+b=c+1三种情况,以及对边长最小值(正数最小一般取1)和典型有效值的考察。

合起来设计用例,用表格呈现:

编号abc预期结果覆盖内容
1555等边有效,等边
2556等腰有效,等腰
3456普通三角形有效,普通
4347非三角形无效,两边和等于第三边
51210非三角形无效,两边和小于第三边
6045非三角形无效,边的非法值
7559非三角形(退化/等腰临界)边界,等腰加退化

提示:等价类和边界值经常配合使用——等价类负责"每类一个代表",边界值负责"在临界点附近多取几个"。出题人让你"用两种方法组合设计"时,别只写等价类,边界附近必须补用例。

3.3 控制流图与环路复杂度:画图加计算

这类题一般给一段代码,让你画出控制流图、计算环路复杂度、找出独立路径。控制流图的画法:顺序结构画成连续的节点,每个判定节点分出真和假两条边,汇合处再并成一个节点。复合条件(如A && B)在画控制流图时通常当成一个判定节点处理,但做条件组合覆盖时要拆开,这个区分前面已经踩过,这里再强调一遍。

环路复杂度V(G)有三种等价算法:一是V(G) = E - N + 2,其中E是边数、N是节点数;二是V(G) = P + 1,P是判定节点(谓词节点)的个数;三是V(G) = 区域数(含外部无界区域)。三种方法算出来应该完全一致,考试时我习惯用第二种快速估一下,再用第一种精确核对。

得到V(G)之后,独立路径数就等于V(G),然后依据这些路径设计测试用例。基本路径测试的核心思想就是让测试用例覆盖所有独立路径,保证每条边至少走一次。常见考点还包括"环形复杂度代表程序独立路径的条数,也代表测试需要的最少用例数"这句话的判断。

3.4 判定表与因果图习题的处理套路

判定表题的套路非常固定,按步骤走不会出错。先列条件桩(所有输入条件),再列动作桩(所有可能的输出动作),然后确定规则数——如果n个条件每个取真取假,理论上是2^n条规则。接着逐条填条件项和动作项,最后对相同动作的规则做合并简化。

步骤操作内容易错点
1列条件桩与动作桩漏掉隐含条件
2确定规则数2^n条件个数数错
3填条件项真假取值漏行
4填动作项并简化简化时丢掉有效规则

因果图是在判定表之前用图形表达输入与输出的逻辑关系,涉及原因(输入)、结果(输出)以及几类约束:E(排斥,两者不能同时为真)、I(包含,至少一个为真)、O(唯一,有且仅有一个为真)、R(要求,一个为真则另一个必须为真)、M(强制,一个为真则另一个必须为假)。做题时先把原因结果列清楚,画图,再转判定表,最后生成用例。因果图题的难点在转向判定表这一步,规则数一多容易数乱,我建议用编号一行一行对,别跳步。

3.5 测试级别与策略类简答题的答题模板

这类题看着简单,但想拿满分得讲结构。比如"简述单元测试和集成测试的区别",别只写一句"单元测试测模块,集成测试测模块之间",要分维度答:测试对象不同(单元测试针对单个模块或函数,集成测试针对模块间的接口与协作)、测试依据不同(单元测试依据详细设计,集成测试依据概要设计)、发现问题类型不同(单元测试找模块内部逻辑错误,集成测试找接口和数据传递问题)、执行时机不同(单元测试在编码后,集成测试在单元测试通过后)。再比如"Alpha测试和Beta测试的区别",抓住测试地点(开发方场所 vs 用户场所)、测试人员(内部人员 vs 真实用户)、目的(发现明显问题 vs 收集真实反馈)三个点来答,层次清晰就是分。

4. 参考答案的正确打开方式

4.1 什么时候看答案才有效

参考答案是双刃剑,用好了事半功倍,用不好就是自我欺骗。我的建议是:任何一道题,先自己完整做一遍,尤其是白盒覆盖和环路复杂度这种计算题,必须独立推完、写出用例再来对答案。对的时候不要只看结果对不对,重点看用例设计的思路和答案差在哪——比如是不是漏了某个边界值,是不是把条件拆解的粒度搞错了。我见过太多同学直接翻答案"看懂了",觉得自己会了,结果临场一算全错。看懂和自己会之间隔着一道执行的墙,只有亲手推过去才算真掌握。

4.2 错题归档的三个维度

错题不要只抄一遍答案就完事,按三个维度归档才能真正提升。概念维度:因为概念不清导致的错,比如把验证和确认搞反了、把Fault和Defect混了,这类要回去补概念。方法维度:方法选错了,比如该用判定表的题用了边界值,这类要总结"什么题该用什么方法"的判断规则。计算维度:算错了、漏算了,比如环路复杂度E数漏了一条边,这类要专门练计算,把三种算法各练几遍互相验证。每道错题标上属于哪个维度,复习时按维度集中突破,效率比单纯刷题高得多。

4.3 计算题的验算技巧

计算题最大的价值在于"算完能自己验,不用等答案"。环路复杂度可以用三种方法算两遍对拍,第一种和第二种结果不一致就说明有地方数错了。白盒覆盖题可以拿设计好的用例代回程序,一步步手动执行,看是否真的覆盖到了目标语句、判定或路径——这一步很多人省了,结果写的用例根本覆盖不全自己还不知道。等价类题则检查每个等价类是否至少被一个用例覆盖,有没有哪个无效等价类被漏掉。这些验算技巧练熟了,考场上你甚至能在交卷前自己纠出一两个错。

5. 高频踩坑与排查速查

5.1 覆盖率概念混淆引发的连锁错误

最高频的坑就是覆盖率概念搞混,一个错带出一串错。典型表现:把判定覆盖当成条件覆盖,写的用例只让判定取到真假,没让每个条件都取到真假;或者把条件组合覆盖理解成"每个条件取真取假",忽略了"组合"。排查方法很简单:判定覆盖看的是整个判定表达式的结果,条件覆盖看的是每个原子条件的取值,条件组合看的是同一判定内条件取值的各种搭配。做题时先在草稿纸上把每个判定的原子条件列出来,标好编号,再逐条设计,就不容易乱。

5.2 等价类划分的争议边界

等价类题的争议多半出在划分标准上。同一个输入集合,按不同标准能划出不同的等价类,比如三角形题里"等腰"和"等边"到底算不算两个独立有效类,有的答案算,有的不算。应对办法是:先看题目的输出分类,题目要求判几种结果,你就往几个有效等价类上靠,让有效等价类和可能的输出一一对应。还有就是无效等价类一个数据只能覆盖一个无效类,不能一个非法输入同时测两个无效条件,这是铁律,违反了算错。

5.3 环路复杂度常见的三种算错

第一种,边数E数错,尤其是复合条件画成多个节点时边数变了没重数;第二种,判定节点P数错,把顺序结构里的普通节点也当成了判定节点;第三种,把复合条件拆成多个判定后再算,导致P偏大。规避方式是用两种方法各算一遍交叉验证:先用P+1快速估,再用E-N+2精算,两个结果必须一致,不一致就重画控制流图。这个习惯看着笨,但考场上能救回好几分。

5.4 简答题写得像不像"参考答案"

简答题丢分往往不是不会,而是写得太随意、没有结构。我的经验是按"分点+关键词+一句解释"来写,每一点都用关键词打头,后面跟一句说明为什么。比如答测试原则,不要流水账,列成:测试是为了发现错误;测试用例应包含合理和不合理的输入;程序员应避免测试自己的程序;测试用例应长期保留;严格执行测试计划。每点再补半句解释,卷面清晰,得分点全踩中。参考答案的评分是按关键词给分的,你写再多废话,关键词没出现也白搭。

6. 从习题到上手:把这一章真正学扎实的路径

6.1 手推一遍胜过看十遍答案

软件测试这一章最忌讳的就是"看答案学"。白盒覆盖、环路复杂度、判定表这些内容,看别人做一遍觉得简单,自己上手就出错。我的建议是找一张白纸,把教材上的经典例题盖住答案,自己从头推一遍:拆条件、列判定、设计用例、代回验证、算复杂度。推完再对答案,把差异点记下来。同一个套路推三到五道题,手就形成肌肉记忆了,考试时看到类似的程序段,思路自动就出来了。这个投入产出比非常高,比重看一遍书强太多。

6.2 用工具验证你的测试用例

如果你想让课程习题和真实工程接上,可以拿一门语言把题目里的程序真正跑起来。用Python的unittest或pytest写测试用例,把白盒覆盖题里的用例一条条实现,运行看结果是否符合预期。进阶一点,可以用覆盖率工具(比如Python的coverage、Java的JaCoCo、C的gcov)看看自己写的用例到底覆盖了多少语句和分支,再和手工推的结果对照。你会发现手工推的覆盖率和工具统计的覆盖率往往有出入,这个差异恰恰是理解覆盖本质的最好切口。工具不会骗你,它统计的语句覆盖、分支覆盖是真实执行的痕迹。

6.3 从课程习题到真实项目

课程习题里的程序段都是精心简化过的,真实项目复杂得多,但底层的测试思想完全通用。等价类划分和边界值在真实接口测试里天天用,判定表适合梳理复杂的业务规则,场景法适合设计端到端流程。你可以拿一个小项目练手,比如自己写一个计算器或待办清单程序,先写测试用例再做功能,体会一下测试驱动开发的思路。把教材里学的方法用在真实代码上,你会对"为什么要有这些方法"有完全不一样的理解——那时候再回头看习题,会觉得当年的自己算用例时漏掉边界值是理所当然的,因为没在真实场景里吃过亏。

最后说个我自己的体会:软件测试这一章,是所有软件工程章节里"投入就能立刻看到回报"的一章。概念背了就有分,方法练了就能用,用它去面试还能直接变现。我见过太多同学在这一章因为嫌算用例麻烦而放弃,结果大题白白丢十几分,特别可惜。真正动手把白盒覆盖和黑盒用例这两块推熟,剩下的都是顺手的事。你要是正在啃这一章,别急着翻答案,先拿张纸自己算——算错的地方,才是你真正需要学的地方。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/1 11:32:10

Kubernetes 入门:kubectl 核心命令与第一个 Pod 部署实战

说实话,我第一次在生产环境接触 Kubernetes 时,不是在测试集群里,而是被拉去处理一个半夜报警的裸金属集群。当时我连 kubectl 都没完全吃透,只能一边翻官方文档一边敲命令,脑子里唯一的念头就是把那个总是 CrashLoopB…

作者头像 李华
网站建设 2026/10/1 11:31:20

Eclipse ADT 下 Android 欢迎界面 Splash 实现与踩坑

做 Android 这些年,经常有人拿着一个老工程来问我:用 eclipse 还能不能把一个完整的 android 项目从头跑到尾。我的答案一直是能,但前提是你得把工具链的版本关系捋顺。这次我拿手里一个练手项目"博学谷"来说事,它是一个…

作者头像 李华
网站建设 2026/10/1 11:31:19

Word表格制作教程:插入、行高列宽、跨页表头与打印避坑

做Word表格这件事,表面上看是点几下鼠标的功夫,真到了要交材料的时候,问题全冒出来了:表格莫名其妙跳到下一页、表头到第二页就消失、明明调好的列宽一刷新全乱、打印出来边框缺了几条线。我前几年帮人改过一份三十多页的投标文件…

作者头像 李华
网站建设 2026/10/1 11:31:17

基于微信小程序与SSM的考务考场管理系统设计与实现

公务员和事业单位考试,考务管理一直是很多单位的痛点。线下考场安排靠Excel手工排,考生信息审核靠人工核对,考试当天还要打印一堆纸质签到表,监考老师来回核对身份。遇到大规模考试,考务人员加班加点不说,还…

作者头像 李华
网站建设 2026/10/1 11:30:19

Archery数据查询规范配置实战:从权限收紧到审计闭环

"Archery这平台,做数据库运维的应该都听过。它把SQL审核、查询、执行、慢日志这些零散的活收敛到一个Web界面里,算是开源工具里比较能打的一套。但说实话,最近两年我帮几家团队落地它,发现大部分人都只关注"审核"和…

作者头像 李华
网站建设 2026/10/1 11:29:31

C++20 Concepts 实战:终结模板报错墙与 SFINAE 地狱

模板报错墙、 enable_if 地狱、SFINAE 玄学……这些词如果你都熟,说明你已经在 C 模板编程里摸爬滚打不少年了。C20 的 Concepts(概念)就是来解决这些问题的,它给模板加上了“类型约束”,让编译器能在报错时直接告诉…

作者头像 李华