想象你是一位探险队长,手里拿着一张代码海岛的藏宝图。队员们一次次出发测试,回来后你在图上把走过的路涂上颜色——这段路踩过了,涂一格;那个岔路口拐过一次,画一笔。图上被涂色的比例,就是“测试覆盖率”。它是个好东西,但一不小心就会骗人:有人绕着海岸线走了九成,图上一大片颜色,可宝藏偏偏藏在从未踏足的山洞里。高覆盖率不等于测试做得好,低覆盖率也不一定危险。真正专业的做法是把这张图用科学:知道四种涂色刻度分别说明什么、用好测绘工具、设定合理的探索目标、识破地图上的黑洞、用空白处指导下一步、并在营门口设一道检查站。这篇内容,就是带你学会这套“藏宝图管理法”。

岗位关联

对 AI 从业者而言,模型服务、数据处理、平台代码都靠测试质量兜底。学会覆盖率管理,你就能用一张量化地图支撑发布决策,而不是拍脑袋说“测过了”。

目录
  1. 可视化演示
  2. 覆盖率类型:四种探路刻度
  3. 覆盖率工具:探险队的测绘装备
  4. 目标设定:给探险划出合理边界
  5. 盲区识别:地图上的黑洞与假象
  6. 测试改进:用空白处指导下一步
  7. 质量门禁:出发前的检查站
  8. AI 应用场景
  9. Python 演示
  10. 常见误区
  11. 面试题

可视化演示

展示系统处理流水线、实时性能指标曲线及多方案对比分析,包含数据流转、吞吐延迟监控与方案评估。

本节配有交互动效(进入视口后自动加载,约 3KB)。

系统可视化 处理流程:输入→处理→模型→输出 性能监控:实时指标 P=L×T

覆盖率类型:四种探路刻度

探险队每踩过一行代码,队长就在地图上涂一小格。过了一个月,地图上 80% 的路被涂上了颜色——这就是最直白的“行覆盖率”。可光知道走过的比例还不够,老练的队长会追问三个更刁钻的问题:岔路口的两条方向都踩过了吗?一条完整的路线从头到尾走通过吗?每一块路标真的独立影响过最终判断吗?这三个问题,分别对应分支覆盖率、路径覆盖率和 MC/DC 覆盖率。

这四个概念颗粒度从粗到细:行覆盖率只关心“这行代码有没有被执行过”,回答的是地图上涂了多少色;分支覆盖率关心“每个判断的每个出口是否都走到过”,相当于岔路口两个方向都要踩一遍;路径覆盖率关心“函数内所有可能的执行路线是否都完整走通”,是整条探险路线的串联;MC/DC 则更进一步,要求“每一个条件都独立地改变过一次判定结果”,好比验证每块路标确实单独改变了方向,而不是跟着别的路标混日子。

行覆盖率是业界最常用、工具支持最成熟的指标,也是藏宝图的第一层底色。它的计算公式如下,注意分母只统计“可执行代码行”,注释、空行、纯声明都不算数:

所以,拿到覆盖率报告先别激动。80% 的行覆盖率只说明探险队把八成道路各踩过一遍,至于岔路口嘛,可能一直只往右拐。想真正看透整张地图,就要把四种刻度同时摆出来互相印证,缺了任何一把尺子,地图都有可能说谎。

行覆盖率=被执行过的代码行数可执行代码总行数×100%\text{行覆盖率} = \frac{\text{被执行过的代码行数}}{\text{可执行代码总行数}} \times 100\%
一句话理解:行覆盖率就是“探险队真正踩过的路”占“整座岛上值得走的路”的比例。
  1. 分子被执行过的代码行数:统计测试运行时真正被 CPU 执行到的语句行,也就是探险队真正踩过的路。
    被执行过的代码行数\text{被执行过的代码行数}
  2. 分母可执行代码总行数:去掉注释、空行和纯声明后的有效代码行,是整座岛上值得走的全部道路。
    可执行代码总行数\text{可执行代码总行数}
  3. 百分比换算分子除以分母再乘以 100%,得到 0% 到 100% 的覆盖比例,用来横向对比不同模块的探索充分度。
    ×100%\times 100\%

覆盖率工具:探险队的测绘装备

探险队不能靠肉眼记路,得有罗盘、地图册和记账本。代码项目也一样,不同语言有各自的测绘装备:Java 生态常用 JaCoCo,Python 常用 coverage.py,JavaScript 常用 Istanbul 或 Vitest 内置的覆盖率能力。装备本身不产生质量,关键看会不会用——选错工具就像拿着量角器去测海拔,报告再精确也是白搭。

用工具的四个正确姿势,对应四种场景:第一是工具选型,要匹配语言、构建链和团队习惯;第二是增量统计,只统计本次改动新增代码的覆盖情况;第三是CI 集成,把覆盖率采集塞进流水线,每次提交自动出报告;第四是报告解读,不要盯单次数值,要看趋势、看模块差异、看未覆盖行的分布。

其中最值得养成习惯的是“增量覆盖率”。全量覆盖率像整座海岛的累计探索度,会被历史涂色的大片区域冲淡;而每次提交的风险,恰恰集中在新增的几十行代码上。增量覆盖率就是专门给“新画的路”记账的:

好的测绘装备能让探险队在补给时一秒钟看清“这次新画了多少地图、哪些新路还没踩过”。工具不是摆出来好看的,而是每次出发前用来算清楚账的——算不清账的探险队,走得再远也找不到宝藏。

增量覆盖率=本次改动中被覆盖的新增行数本次改动的总新增行数×100%\text{增量覆盖率} = \frac{\text{本次改动中被覆盖的新增行数}}{\text{本次改动的总新增行数}} \times 100\%
一句话理解:增量覆盖率回答的是“这趟新探险画出来的地图,有多少是真正踩过验证过的”。
  1. 分子本次改动中被覆盖的新增行数:只统计本次提交新增的代码中,被已有或新增测试真正执行到的行。
    本次改动中被覆盖的新增行数\text{本次改动中被覆盖的新增行数}
  2. 分母本次改动的总新增行数:本次提交实际新增的所有可执行代码行,作为这次改动的风险总盘子。
    本次改动的总新增行数\text{本次改动的总新增行数}
  3. 比例换算两者相除并乘以 100%,得到 0% 到 100% 的数值,数值越低说明新路越缺乏验证。
    ×100%\times 100\%

目标设定:给探险划出合理边界

成熟的队长不会喊“把整座岛走遍”,而是拿出海图分区规划:埋宝藏的核心山峰重点探查,边缘渔村走一圈就算数。如果对每个模块都要求同样高的覆盖率,队员要么被累垮,要么开始伪造路线。覆盖率目标也是一样,一条线划到底,不是激励,是灾难。

目标设定有四条原则。分层目标:核心模块定 90%,普通模块定 70%,工具脚手架定 50%,不让珍贵的人力耗在没价值的地方。风险驱动:出错影响大、用户路径长的模块,目标往上调;内部工具、一次性脚本,往下压。动态调整:目标不是刻在石头上的,要根据历史完成情况每季度复盘修订。团队共识:目标必须是团队认账的数字,单方面压下来的指标只会催生形式主义。

一个可执行的设定方式是“基线 + 步长”。先看当前覆盖率是多少作为基线,再定每个迭代往上加多少步长,分阶段逼近理想值。这样团队不会因为一步到不了位就干脆躺平:

目标不是贴在墙上的口号,而是地图上用虚线画出的探索边界。定得太狠,队员会绕路造假象;定得太松,藏宝图永远画不完。分层、分步、大家一起商量着定,探索才能细水长流。

覆盖率目标=历史基线+步长×迭代周期\text{覆盖率目标} = \text{历史基线} + \text{步长} \times \text{迭代周期}
一句话理解:把大目标拆成每轮探险只多画一圈,既看得到进步,又不会被吓退。
  1. 历史基线当前模块最近一次的实测覆盖率,是探险队出发的位置。
    历史基线\text{历史基线}
  2. 步长每个迭代周期计划提升的覆盖百分点,步子太大容易诱发造假。
    步长\text{步长}
  3. 迭代周期从基线到评估时点经过了几个迭代,与步长相乘得到累计提升幅度。
    迭代周期\text{迭代周期}

盲区识别:地图上的黑洞与假象

探险队最怕的不是没走过的路,而是地图上明明显示“已涂色”、实际上根本没人探过的地方——比如一片画满脚印却从未有人钻进去的雾谷。覆盖率报告里,这样的假象区域就叫盲区。识别盲区,是让覆盖率数字可信的第一步。

典型的盲区有四类。死代码:永远不会被触达的代码,探险队画了一条通往悬崖的路,路是真路,但谁也走不过去,白白虚高覆盖率。异常分支:if 的正常分支天天被测试宠幸,else 和 except 却常年无人问津,一旦线上出错,往往就错在这里。状态组合:多个布尔条件相互搭配,测试只试了其中两三种组合,就把组合地图画满了。异步场景:回调、并发、事件循环里的代码,覆盖率工具经常数不清楚,形成统计盲区。

状态组合是数学上的硬骨头:如果判断里有 n 个布尔条件,穷举全部组合需要 2 的 n 次方个用例。条件一多,盲目追求路径级覆盖会立刻爆炸:

识别盲区的意义在于,涂地图之前先问一句:这一格的颜色,是探险队真走出来的,还是测绘仪自己脑补的?只有把死代码、异常路径和组合爆炸这些黑洞逐个找出来,覆盖率数字才配得上“质量指标”这四个字。

全组合用例数=2n\text{全组合用例数} = 2^{n}
一句话理解:条件数每多一个,需要的用例数就翻一倍——这是探险队绕不过去的“岔路爆炸”。
  1. 条件数 n判定语句中参与逻辑运算的布尔条件个数,每个条件在真和假之间二选一。
    nn
  2. 指数增长 2 的 n 次方每个条件两种取值,n 个条件就能组合出 2 的 n 次方种情况。
    2n2^{n}
  3. 全组合用例数穷举所有组合需要的测试用例总量,当 n 超过 5 时,全组合策略就变得不现实。
    全组合用例数\text{全组合用例数}

测试改进:用空白处指导下一步

地图最大的价值是指引下一步——哪里空白最多、风险最大,哪里就值得下一支探险队先去探。覆盖率管理的落脚点,不在“刷数字”,而在“根据数字做决策”。这是从“记录地图”到“使用地图”的关键一跃。

覆盖率驱动测试改进,核心是四件事。覆盖驱动:对照覆盖率报告圈出未覆盖的高风险区域,为它们补测试。优先级排序:不是哪里空白补哪里,而是先补“风险高、成本低”的地方,让有限的测试人力花在刀刃上。回归防护:新增的有效用例要沉淀进回归集,防止后续改动悄悄破坏刚涂上的区域。消除冗余:那些跑一遍不增加任何新覆盖的用例,要大胆清理,否则回归集只会越拖越臃肿。

给补测排优先级,可以用一个简单的分数来建模——风险分越高、未覆盖比例越大、补测成本越低,越应该先动手:

覆盖率管理的真正功力,是像经验丰富的队长看地图那样:用空白的分布决定派谁去哪里,用涂色的增长速度判断探险效率。地图会越画越满,但每一次下笔都应该有理由,而不是为了把某个数字凑好看。

测试优先级=风险分×未覆盖率补测成本\text{测试优先级} = \frac{\text{风险分} \times \text{未覆盖率}}{\text{补测成本}}
一句话理解:高风险、大空白、低成本的区域先探,这是探险队投入产出比最高的路线。
  1. 风险分模块出错造成的影响程度,核心路径给高分,边缘工具给低分。
    风险分\text{风险分}
  2. 未覆盖率该模块尚未被测试覆盖的代码比例,空白越大越值得优先探索。
    未覆盖率\text{未覆盖率}
  3. 补测成本补一条有效用例所需的时间与数据准备成本,成本越低,排序越靠前。
    补测成本\text{补测成本}

质量门禁:出发前的检查站

每次探险队要出营地,基地门口都设有一道检查站:新画的地图够不够格,不够就回去补。这道检查站,对应工程实践里的“质量门禁”。它把覆盖率从“事后统计”变成“事前拦截”,让每一份代码都得带着足够的地图成果才能上路。

质量门禁的运作方式不难理解:把覆盖率阈值接入持续集成流水线,代码一提交,就自动跑测试、自动算覆盖率、自动判断达不达标。不达标就流水线失败、阻止合并,把风险挡在主分支门外。规则通常采用“增量 + 全量”双阈值,既卡住本次新增的风险,又守住历史质量的底线。

门禁设计要警惕反模式:阈值不是越高越好。定得太高,团队为了过门禁,就会写一堆“为了凑数”的假测试——断言形同虚设、路径刻意绕行。真正有效的门禁是分级的:核心模块从 90% 起步,边缘模块 70% 即可;同时让门禁数据持续回流,成为下一轮测试改进的依据,形成闭环:

检查站不是用来刁难探险队的,而是保证每一次出发的新地图都真实可用。门禁把“覆盖率达到多少”从自觉变成了纪律,也让质量成了一个可审计、可追溯、可讨论的工程动作。有了它,藏宝图上的每一格颜色,都变得有据可查。

门禁通过=(增量覆盖率≥θ1)∧(全量覆盖率≥θ2)\text{门禁通过} = (\text{增量覆盖率} \geq \theta_1) \wedge (\text{全量覆盖率} \geq \theta_2)
一句话理解:增量覆盖率过了第一道竿、全量覆盖率过了第二道竿,两个都达标,探险队才能带着新地图出门。
  1. 增量覆盖率阈值 θ1本次新增代码必须达到的覆盖率下限,防止新画的路线夹带私货。
    增量覆盖率≥θ1\text{增量覆盖率} \geq \theta_1
  2. 全量覆盖率阈值 θ2整个代码库必须维持的覆盖率基线,防止历史地图质量悄悄滑坡。
    全量覆盖率≥θ2\text{全量覆盖率} \geq \theta_2
  3. 逻辑与 ∧两个条件必须同时成立,只要一个不达标,门禁就判定失败、拦截提交。
    ∧\wedge

AI 应用场景

持续集成质量门禁

阶段:持续集成与交付(CI/CD)

解决的问题:传统方式靠人工 review 判断测试是否充分,漏判多、口径不一。AI 项目里模型服务、推理代码改动频繁,用覆盖率门禁自动拦截增量覆盖率不足的提交,把“测试充分性”从主观感受变成可量化的硬卡点,让探险队每次出门都经过检查站。

具体案例:某 AI 推理服务仓库在 CI 流水线上配置质量门禁:新增代码行覆盖率不低于 80%、分支覆盖率不低于 70%,不达标则流水线失败、PR 无法合并。一个只加了新后处理分支却没补测试的提交在合并前被拦截——后来线上果然出现了该分支的格式异常,门禁成功挡下了一次事故。

覆盖率盲区驱动的补测计划

阶段:测试策略优化与质量改进

解决的问题:面对庞大的历史代码,测试团队不知道优先补哪里。用覆盖率报告识别出未覆盖的异常分支和死代码盲区,按风险分排序制定补测计划,让有限的测试人力先填最危险的坑,而不是按人头平均分配。

具体案例:某模型服务的数据校验模块行覆盖率为 55%,覆盖率报告显示大量未覆盖的异常分支集中在“输入格式非法”的处理路径上——正是线上偶发崩溃的高发区。测试团队针对盲区补了 20 条用例,分支覆盖率提升到 82%,线上崩溃率明显下降。

覆盖率引导的回归范围裁剪

阶段:版本发布与回归测试

解决的问题:每次发版全量回归耗时数小时,测试成本居高不下。基于增量覆盖率和代码变更影响面,动态裁剪回归范围,把测试资源集中在真正受影响的模块上,让探险队不必每次把整座岛重新走一遍。

具体案例:一个 AI 训练平台在发新版时,先统计自上次发布以来的增量覆盖率,只对未覆盖变更的模块快速补一轮冒烟测试。回归时间从 5 小时降到 1.5 小时,缺陷检出率基本持平,发布节奏明显加快。

Python 演示

python47 行
"""迷你测试覆盖率统计器:根据执行轨迹计算覆盖率并通过质量门禁。"""  class MiniCoverage:    def __init__(self, total_lines, branch_map, threshold=0.7):        self.total_lines = total_lines       # 源文件可执行总行数        self.branch_map = branch_map         # 分支点 -> 出口行列表 {4: [5, 6]}        self.executed_lines = set()          # 已执行行号集合        self.executed_branches = set()       # 已走分支方向集合 {(4, 5), (4, 6)}        self.threshold = threshold           # 全量行覆盖率门禁阈值     def run(self, trace):        for line_no in trace:            self.executed_lines.add(line_no)        for src, dests in self.branch_map.items():            if src in self.executed_lines:                for d in dests:                    if d in self.executed_lines:                        self.executed_branches.add((src, d))     def line_coverage(self):        return len(self.executed_lines) / self.total_lines     def branch_coverage(self):        total = sum(len(v) for v in self.branch_map.values())        return len(self.executed_branches) / total if total else 1.0     def uncovered_lines(self):        all_lines = set(range(1, self.total_lines + 1))        return sorted(all_lines - self.executed_lines)     def gate_passed(self):        return self.line_coverage() >= self.threshold  if __name__ == "__main__":    cov = MiniCoverage(        total_lines=12,        branch_map={4: [5, 6], 8: [9, 11]},        threshold=0.7,    )    trace = [1, 2, 3, 4, 5, 6, 8, 9, 10, 12]    cov.run(trace)    print("行覆盖率: %.0f%%" % (cov.line_coverage() * 100))    print("分支覆盖率: %.0f%%" % (cov.branch_coverage() * 100))    print("未覆盖行: %s" % cov.uncovered_lines())    print("质量门禁: %s" % ("通过" if cov.gate_passed() else "未通过"))
目的:模拟一个微型覆盖率工具,根据测试执行轨迹计算行覆盖率、分支覆盖率,识别未覆盖盲区,并判断是否通过质量门禁——把“藏宝图涂色”变成可运行的代码。
  1. self.executed_lines = set()用集合记录已执行行号,天然去重,比列表更高效。
  2. def run(self, trace):模拟一次测试执行,喂入一条行号轨迹,探险队开始踩路线。
  3. if d in self.executed_lines:只有出口行也执行过,才认定这个分支方向被真正走过。
  4. return len(self.executed_lines) / self.total_lines行覆盖率的核心公式:已涂色格数除以总格数。
  5. return sorted(all_lines - self.executed_lines)用集合差集找出未覆盖行,这就是地图上的盲区清单。
  6. return self.line_coverage() >= self.threshold质量门禁的判定逻辑:覆盖率不够阈值,检查站不放行。

常见误区

误区“我把行覆盖率打到 100% 了,我的测试绝对没问题!”很多人把行覆盖率当成质量的终极证明,觉得数字满了就可以高枕无忧。

正解行覆盖率只说明每行代码至少被执行过一次,不说明执行时的断言是否有效、分支方向是否齐全。就像探险队把岛上每条路都踩了一遍,但岔路口可能只走了一个方向、路标也没验证过。100% 行覆盖率配上 50% 分支覆盖率的情况很常见,缺陷照样能藏在漏掉的 else 分支里。覆盖率是过程度量,不是质量结论。

为何常见:行覆盖率数字直观、工具默认展示,人天生容易把“数字达标”等同于“任务完成”。

误区“质量门禁设 90%、95% 总没错吧?越高越保险!”管理层常觉得阈值拉高就等于质量拉高。

正解当目标高到团队必须给死代码、样板代码补测试时,测试就会变形——写无断言的假测试、刻意构造执行路径绕开逻辑。覆盖率目标的本质是“投入产出平衡点”:核心模块定高,边缘模块定低,再配合基线步长滚动提升,而不是一刀切顶到天上。

为何常见:管理者想用单一数字简化质量考核,忽略了测试成本随覆盖率上升而急剧增加的边际规律。

误区“全量覆盖率 80%,这次改动就那么几行,不用看了。”很多人觉得全量数字稳,单次改动无需操心。

正解全量覆盖率是整座海岛的累计探索度,会被历史大片涂色冲淡。本次改动的风险集中在新增代码上,如果新增的几十行完全没被测试触及,全量数字依然漂亮,缺陷却已经在新代码里发芽。增量覆盖率才是每次提交最该盯的仪表盘。

为何常见:全量数值大且稳定,给人一种“整体安全”的安全感,掩盖了局部新增的真实风险。

误区“我们 MC/DC 覆盖率 90%,系统绝对安全!”有人把最严格的覆盖率标准当成万能护身符。

正解MC/DC 只验证“每个条件独立影响判定结果”的组合充分性,无法覆盖循环次数问题、状态时序问题、资源泄漏和并发竞态。它是为航空控制这类安全关键软件准备的,普通 Web 服务每个模块都强上 MC/DC,成本和收益严重不成比例。

为何常见:MC/DC 听起来最严格、最专业,人们容易把“严格”误当成“全面”。

误区“工具显示覆盖率 95%,代码肯定被测得很全面。”很多人对工具输出不加怀疑。

正解覆盖率报告依赖插桩方式和统计口径,死代码、无人调用的 getter/setter 都会虚高数据;工具也不会告诉你测试里有没有真的写断言。报告是地图,不是宝藏本身。高覆盖率区域仍需人工抽查,确认那些“覆盖”是有效验证而不是走过场。

为何常见:工具给出精确到小数点的数字,而人天然信任机器输出的权威性,忘了先问统计口径。

面试题

Q1. 计算行覆盖率时,分母应该是哪一项?

单选题 · easy

  • A.源文件总行数含注释空行
  • B.可执行代码行的总数← 正确答案
  • C.所有测试用例的数目
  • D.代码中的分支语句数

答案:B。行覆盖率的分母只统计“可执行代码行”,注释、空行、纯声明都被排除在外。就像藏宝图只统计值得走的路,不含岩石和草丛;A 把无意义行也算了进去,C、D 则完全跑偏。

Q2. 下列哪一项最能代表“分支覆盖率”的考察对象?

单选题 · easy

  • A.每个岔路口是否两条都走过← 正确答案
  • B.每条大路是否都完整走完
  • C.每个路标是否都发挥作用
  • D.每面旗帜是否都已经升起

答案:A。分支覆盖率考察每个判断点的每个出口是否都被执行过,正是“岔路口两个方向都要走”。B 是路径覆盖率,C 是 MC/DC,D 是凑数选项。

Q3. 关于行覆盖率与分支覆盖率的关系,正确的是?

单选题 · mid

  • A.行覆盖率达标则分支必达标
  • B.分支覆盖率必然等于行覆盖率
  • C.两者维度不同不能互相代替← 正确答案
  • D.分支覆盖率一定低于行覆盖率

答案:C。行覆盖率管“每行是否执行”,分支覆盖率管“每个出口是否走到”,两者统计对象不同。走完一行代码不等于两个分支都走到,因此不能互相替代,数值高低也没有必然关系。

Q4. MC/DC 覆盖率比普通分支覆盖率更严格,原因是?

单选题 · mid

  • A.要求每个条件独立影响判定结果← 正确答案
  • B.要求每个分支至少被执行两次
  • C.要求覆盖率达到百分之百才行
  • D.要求所有路径被完整地走一遍

答案:A。MC/DC 的核心是“每个条件单独改变一次,判定结果也随之改变”,确保没有条件在滥竽充数。B 不是 MC/DC 的定义,D 是路径覆盖率的追求,C 与覆盖率类型无关。

Q5. 为什么要重点关注“增量覆盖率”而非只看全量覆盖率?

单选题 · mid

  • A.全量覆盖率的统计成本往往更高
  • B.新改动的代码才是风险集中区← 正确答案
  • C.增量覆盖率更容易达到预定的目标
  • D.全量覆盖率完全没有参考的价值

答案:B。每次提交的风险集中在新增代码上,全量覆盖率会被历史大片涂色稀释,掩盖局部风险。增量覆盖率就像只给新画的路线记账,能精确反映本次改动的测试充分度。

Q6. 某个模块行覆盖率看似很高,却在线上频繁出错,最可能的反模式原因是?

单选题 · hard

  • A.测试只覆盖了快乐的正常路径← 正确答案
  • B.测试工具的版本选择得比较老
  • C.团队把行覆盖率目标定得偏低
  • D.开发人员没有编写单元测试

答案:A。高行覆盖率伴生高线上故障,常见原因是测试全打在正常路径上,异常分支、边界条件全被跳过——图涂得满,但都在安全区打转。这也说明行覆盖率不能单独作为质量指标。

Q7. 一个判定包含 3 个条件(A && B && C),要满足 MC/DC 要求,至少需要多少个测试用例?

单选题 · extreme

  • A.至少需要三个测试用例才行
  • B.至少需要四个测试用例才行← 正确答案
  • C.至少需要八个测试用例才行
  • D.至少需要两个测试用例才行

答案:B。MC/DC 要求每个条件独立影响判定结果,n 个条件最少需要 n+1 个测试用例。3 个条件对应 4 个用例;8 个是全组合数量,2 个连每个条件独立影响都验证不到。这是 MC/DC 的经典结论。

Q8. 下列哪些属于常见的代码覆盖率类型?

多选题 · easy

  • A.行覆盖率与分支覆盖率← 正确答案
  • B.路径覆盖率与 MC/DC← 正确答案
  • C.函数覆盖率与条件覆盖率← 正确答案
  • D.网络覆盖率与带宽利用率

答案:ABC。A、B、C 都是常见代码覆盖率类型;D 是网络性能指标,与代码测试无关,属于干扰项。就像藏宝图的“四种刻度”之外,不会混入天气预报。

Q9. 设定覆盖率目标时,应当考虑哪些因素?

多选题 · mid

  • A.模块的业务风险等级高低← 正确答案
  • B.已有测试基线的变化趋势← 正确答案
  • C.团队投入能力与补测成本← 正确答案
  • D.领导拍脑袋定的直觉数字

答案:ABC。目标设定应遵循风险驱动、动态调整、成本可承担的原则,所以 A、B、C 都成立。D 是典型的反模式,拍脑袋定的目标要么吓退团队,要么催生形式化应对。

Q10. 关于“质量门禁”的正确说法有哪些?

多选题 · hard

  • A.门禁失败可以阻断合并提交← 正确答案
  • B.门禁阈值设置得越高就越好
  • C.门禁应区分模块的风险等级← 正确答案
  • D.门禁通过意味着没有缺陷

答案:AC。A 对,门禁卡在 CI 流水线上,不达标就阻止合并;C 对,核心模块应设更高门槛,边缘模块放宽。B 错,阈值过高会诱发假测试;D 错,覆盖率通过只能说明测试够充分,无法证明没有缺陷。