跳转至

黑盒测试

一句话

把被测对象看作一个黑盒:不关心内部怎么实现,只根据需求、规格和可观察的输入输出设计测试。

黑盒测试(Black-box Testing)又称功能测试、行为测试。测试人员只关心输入什么、执行什么操作、应该看到什么结果,不依赖代码结构。因此它既可以在代码完成后执行,也可以在需求或原型阶段提前设计用例。

优点 局限
站在用户和需求视角,容易发现功能缺失和理解偏差 无法知道哪些代码路径没有被执行
用例与实现解耦,重构后仍可复用 需求描述不清时,预期结果难以确定
适合系统测试、验收测试和第三方测试 大量输入可能重复覆盖同一段内部逻辑
不要求测试人员了解实现细节 难以直接定位缺陷所在的代码

黑盒测试不是"随便点一点"。要系统地选择输入,需要下面的用例设计方法。

等价类划分

等价类划分(Equivalence Partitioning)把输入域分成若干类:同一类中的任意一个值,程序的处理逻辑和输出应当相同。于是每个类只需要选一个代表值,就能以较少的用例覆盖较大的输入空间。

等价类分为两种:

  • 有效等价类:符合需求、应当被正常处理的输入;
  • 无效等价类:不符合需求、应当被拒绝或给出错误提示的输入。

设计步骤

  1. 分析需求,列出每个输入条件及其取值范围;
  2. 为每个输入条件划分有效等价类和无效等价类,并编号;
  3. 为每个等价类各设计一条用例;
  4. 有效等价类可以尽量组合到同一条用例中;无效等价类通常一次只覆盖一个,其余输入保持有效。

最后一条很重要:如果一条用例同时放了多个非法输入,程序可能因为第一个错误就返回,后面的非法输入根本没有被检查到,缺陷会被"屏蔽"。

示例:注册年龄

需求:用户年龄必须是 18 到 60 之间的整数(含 18 和 60)。

输入条件 有效等价类 无效等价类
年龄 V1:18 ≤ age ≤ 60 的整数 I1:age < 18
I2:age > 60
I3:非整数,如 20.5、abc
I4:空值或缺失

据此可以设计用例:

编号 输入 预期结果 覆盖的等价类
TC1 age = 25 注册成功 V1
TC2 age = 17 提示年龄不能小于 18 I1
TC3 age = 61 提示年龄不能大于 60 I2
TC4 age = 20.5 提示必须输入整数 I3
TC5 age 为空 提示年龄必填 I4

等价类划分只回答了"选哪些值",还没有回答"选在区间的哪个位置"。边界值分析正好补上这一点。

边界值分析

大量缺陷发生在输入范围的边缘:循环的第一次和最后一次、数组的首尾、金额刚好达到阈值、日期跨月跨年。边界值分析(Boundary Value Analysis)专门选取边界及其邻近值。

对于闭区间 [18, 60],常用"三点法"取:

位置 取值 说明
下界外点 17 刚好无效
下界上点 18 刚好有效
下界内点 19 有效
上界内点 59 有效
上界上点 60 刚好有效
上界外点 61 刚好无效

如果只关心边界本身,可以用"两点法",只取 18、60 以及紧邻的 17、61。对离散的整数域,min-1、min、max、max+1 通常都要覆盖;对连续值或浮点数,则选择"最接近边界且可表示"的值,并注意精度误差。

边界值分析常与等价类划分一起使用:先划分等价类,再在每个类的边界上取值。

更多边界场景:

  • 字符串长度为 0、1、最大长度、最大长度 + 1;
  • 集合/数组为空、只有一个元素、刚好达到容量;
  • 金额为 0、0.01、阈值、阈值 + 0.01;
  • 日期为闰年 2 月 29 日、月末、年末;
  • 分页的页码为 1、最后一页、最后一页 + 1。

决策表

当输出由多个条件的组合决定时,条件之间可能存在 与、或、互斥等关系。决策表(Decision Table)把所有条件组合和对应动作列成表格,能有效发现遗漏的规则和规则冲突。

决策表通常包含四部分:

条件桩 条件项
动作桩 动作项

每一列是一条规则(rule),表示一种条件组合下应执行的动作。

示例:订单折扣

规则如下:

  • 会员且订单满 200 元:8 折;
  • 会员但未满 200 元:9 折;
  • 非会员且满 200 元:有券 9 折,无券 95 折;
  • 非会员且未满 200 元:有券 95 折,无券原价。
条件 / 动作 R1 R2 R3 R4 R5 R6 R7 R8
是会员 Y Y Y Y N N N N
订单满 200 Y Y N N Y Y N N
使用优惠券 Y N Y N Y N Y N
8 折 ✓ ✓
9 折 ✓ ✓ ✓
95 折 ✓ ✓
原价 ✓

观察 R1/R2 和 R3/R4:当"是会员"时,优惠券不影响结果,这两组规则可以合并,用 — 表示无关条件:

条件 / 动作 R1 R2 R3 R4 R5 R6
是会员 Y Y N N N N
订单满 200 Y N Y Y N N
使用优惠券 — — Y N Y N
8 折 ✓
9 折 ✓ ✓
95 折 ✓ ✓
原价 ✓

合并后的 6 条规则各设计一条用例即可。决策表的价值在于:规则数量一目了然,— 和空缺会提醒我们哪里可能漏了规则,同一组合对应多个动作则提示规则冲突。

状态转换测试

有些系统的输出不只取决于当前输入,还取决于当前处于什么状态。例如订单、支付、审批、登录锁定。状态转换测试(State Transition Testing)把系统建模为状态机:

  • 状态:系统在某一时刻的稳定情况;
  • 事件:触发状态变化的外部输入;
  • 转换:从一个状态到另一个状态,可带守卫条件(guard)和动作;
  • 非法转换:当前状态不应接受的事件。

示例:订单状态

stateDiagram-v2
    state "退款中(未发货)" as REFUND_PENDING
    state "退款中(已发货)" as REFUND_SHIPPED

    [*] --> 待支付
    待支付 --> 已支付: 支付成功
    待支付 --> 已取消: 用户取消 / 超时
    已支付 --> 已发货: 商家发货
    已支付 --> REFUND_PENDING: 申请退款
    已发货 --> 已完成: 确认收货
    已发货 --> REFUND_SHIPPED: 申请退款
    REFUND_PENDING --> 已退款: 退款成功
    REFUND_PENDING --> 已支付: 退款驳回
    REFUND_SHIPPED --> 已退款: 退款成功
    REFUND_SHIPPED --> 已发货: 退款驳回
    已完成 --> [*]
    已取消 --> [*]
    已退款 --> [*]

对应的转换表:

当前状态 事件 下一状态 说明
待支付 支付成功 已支付 正常支付
待支付 用户取消 / 超时 已取消 终态
已支付 商家发货 已发货
已支付 申请退款 退款中(未发货) 未发货可退款
已发货 确认收货 已完成 终态
已发货 申请退款 退款中(已发货)
退款中(未发货) 退款成功 已退款 终态
退款中(未发货) 退款驳回 已支付 回到支付状态
退款中(已发货) 退款成功 已退款 终态
退款中(已发货) 退款驳回 已发货 回到发货状态

常见的覆盖要求由弱到强:

覆盖准则 要求
状态覆盖 每个状态至少到达一次
转换覆盖(0-switch) 每条合法转换至少执行一次
N-switch 覆盖 连续 N+1 条转换组成的路径至少执行一次
非法转换覆盖 每个非法事件都被拒绝,且状态不变

例如一条正常路径 待支付 → 已支付 → 已发货 → 已完成 可以覆盖多条转换;而"退款驳回后再次申请退款"需要专门设计,否则 退款中(已发货)→ 已发货 这条回边很容易被遗漏。

其他常用方法

因果图

因果图(Cause-Effect Graphing)先把需求中的原因(输入条件)和结果(输出动作)画成图,再标注约束(互斥、包含、唯一等),最后转换成决策表。它适合条件组合多、条件之间有约束的场景,本质上仍是把组合关系系统化。

正交实验与成对组合

当有多个配置项、每个配置项有多个取值时,全组合数量会爆炸。例如 4 个参数各有 3 个取值,全组合是 3^4 = 81 条。成对(pairwise)组合只要求任意两个参数的取值组合至少出现一次,通常十几条用例就能覆盖大部分由参数交互引起的缺陷。

场景法

场景法从用例的基本流和备选流出发:

  • 基本流:一切顺利的主路径;
  • 备选流:某一步出现异常或选择了其他分支。

把基本流和各备选流组合成场景,覆盖"正常完成、中途取消、失败重试、并发操作"等真实使用方式。它和状态转换测试经常配合使用。

方法如何配合

实际项目中,测试方法通常组合使用:

测试依据 优先方法
单个字段的取值要求 等价类划分 + 边界值分析
多条业务规则的组合 决策表 + 因果图
有状态、有先后顺序的业务 状态转换测试 + 场景法
多配置项、多环境参数 成对组合 / 正交实验
端到端用户流程 场景法

先用系统方法保证"该覆盖的规则都覆盖",再用基于经验的方法补充历史缺陷和特殊场景,参见基于经验的测试。

黑盒测试的局限

黑盒测试无法直接回答下面这些问题:

  • 某段代码是否从未被执行?是否存在死代码?
  • 某个 if 的另一条分支是否可达?
  • 异常处理、资源释放、并发控制是否真的被执行?
  • 输入组合已经很多,哪些组合对应同一条内部路径,哪些组合被遗漏?

这些问题需要打开盒子,借助白盒测试从代码结构角度补充。反过来,白盒测试也不能证明需求被正确实现,两者不是替代关系。

无效等价类为什么要一次只覆盖一个?

如果一条用例同时包含多个非法输入,程序可能在检查到第一个错误时就返回,后面的非法输入根本没有被验证。分开设计可以让每条用例的失败原因唯一,便于定位缺陷;也能避免一个缺陷掩盖另一个缺陷。

边界值分析一定要取 min-1 和 max+1 吗?

不一定。对离散整数域,min-1 / max+1 是紧邻边界的有效测试点;对连续值、浮点数或取值范围极大的域,应取"最接近边界且可表示"的值,并考虑精度。关键是测试边界两侧的行为,而不是机械地加减一。

决策表规则很多时怎么办?

先检查是否存在无关条件(用 — 合并)、互斥条件和不可能组合,通常能大幅压缩规则数。压缩后仍很大时,再考虑成对组合或在风险高的规则上优先设计用例,而不是盲目追求全组合。

小结

  • 黑盒测试依据需求和外部行为,不依赖代码结构;
  • 等价类划分解决"选哪些值",边界值分析解决"选在值域的什么位置";
  • 决策表处理多条件组合,状态转换处理有先后顺序的业务;
  • 成对组合和场景法用于控制组合爆炸、贴近真实使用流程;
  • 黑盒测试擅长验证"做什么",但无法判断"哪些代码没被执行",需要白盒测试互补。

最后更新: 2026-10-27 01:43:13
创建日期: 2026-10-27 01:43:13

广告

人要恰饭的嘛🤑🤑

评论