4、判定表法:业务逻辑复杂时的利器
说实话,很多测试同学一碰到「多个条件组合」的场景就头大。比如登录功能——账号、密码、验证码,三个条件一组合,到底要测多少条用例?
我早年带团队时,有个新人对着登录模块写了 30 多条用例,结果上线还是漏了一个场景:验证码错误但账号密码正确时,系统居然也登录成功了。嗯,这就是典型的「条件组合没覆盖全」。
判定表法,就是专门解决这个问题的。它能把复杂的业务逻辑拆得清清楚楚,让你一条用例都不漏。
4.1 什么是判定表?
判定表,说白了就是一张「条件 → 动作」的对照表。它由四个部分组成:
- 条件桩:列出所有输入条件(比如:账号是否正确、密码是否正确、验证码是否正确)
- 动作桩:列出所有可能的输出结果(比如:登录成功、提示账号错误、提示密码错误、提示验证码错误)
- 条件项:每个条件的具体取值(真/假、有效/无效)
- 动作项:对应条件组合下,应该执行的动作
核心思想:把「条件」和「动作」分离,用表格穷举所有条件组合,再确定每个组合对应的动作。
4.2 条件桩与动作桩
我习惯先列条件桩,再列动作桩。举个例子——登录功能:
| 类型 | 名称 | 说明 |
|---|---|---|
| 条件桩 | C1: 账号是否正确 | 已注册账号 = 正确,未注册 = 错误 |
| 条件桩 | C2: 密码是否正确 | 与账号匹配 = 正确,不匹配 = 错误 |
| 条件桩 | C3: 验证码是否正确 | 输入与图片一致 = 正确,否则 = 错误 |
| 动作桩 | A1: 登录成功 | 跳转到首页 |
| 动作桩 | A2: 提示「账号不存在」 | 停留在登录页 |
| 动作桩 | A3: 提示「密码错误」 | 停留在登录页 |
| 动作桩 | A4: 提示「验证码错误」 | 刷新验证码 |
你想想看,三个条件,每个条件有「正确/错误」两种取值,理论上就是 2³ = 8 种组合。但实际业务中,有些组合是「不可能出现」的,比如账号错误时,密码是否正确其实没有意义——因为系统根本不会去校验密码。
4.3 判定表化简
为什么要化简?因为全排列出来的用例太多了。3 个条件 8 条,4 个条件 16 条,5 个条件 32 条……你不可能全测。
化简的核心原则:合并「动作相同」且「条件取值不影响结果」的列。
我的经验:化简时先看动作桩,把动作完全相同的列找出来。然后检查这些列中,哪些条件取值不同但动作不变——这些条件就是「无关条件」,可以合并。
举个例子,登录功能中:
- 当账号错误时,不管密码和验证码对不对,系统都只提示「账号不存在」
- 当账号正确、密码错误时,不管验证码对不对,系统都只提示「密码错误」
- 当账号正确、密码正确、验证码错误时,提示「验证码错误」
- 只有三者全正确,才登录成功
你看,8 种组合化简后,其实只需要 4 条用例:
| 用例编号 | 账号 | 密码 | 验证码 | 预期结果 |
|---|---|---|---|---|
| TC-01 | 错误 | — | — | 提示「账号不存在」 |
| TC-02 | 正确 | 错误 | — | 提示「密码错误」 |
| TC-03 | 正确 | 正确 | 错误 | 提示「验证码错误」 |
| TC-04 | 正确 | 正确 | 正确 | 登录成功 |
「—」表示该条件不影响结果,可以任意取值。这就是判定表化简的价值——用最少的用例覆盖最多的场景。
4.4 实战案例:登录功能判定表设计
好,我们来完整走一遍登录功能的判定表设计流程。
步骤一:列出条件桩和动作桩
条件桩:
- C1: 账号是否存在于系统中(存在/不存在)
- C2: 密码是否与账号匹配(匹配/不匹配)
- C3: 验证码是否输入正确(正确/错误)
动作桩:
- A1: 登录成功,跳转首页
- A2: 提示「账号或密码错误」(注意:这里不区分是账号错还是密码错,防止暴力破解)
- A3: 提示「验证码错误」,刷新验证码
避坑指南:我曾经遇到一个项目,登录失败时分别提示「账号不存在」和「密码错误」。结果被安全团队打回——这等于告诉攻击者「账号是对的,继续猜密码」。后来统一改成「账号或密码错误」。
步骤二:生成全排列判定表
3 个条件,每个 2 种取值,共 8 种组合:
| 组合 | C1 账号 | C2 密码 | C3 验证码 | A1 登录成功 | A2 账号或密码错误 | A3 验证码错误 |
|---|---|---|---|---|---|---|
| 1 | 不存在 | — | 正确 | ✓ | ||
| 2 | 不存在 | — | 错误 | ✓ | ||
| 3 | 存在 | 不匹配 | 正确 | ✓ | ||
| 4 | 存在 | 不匹配 | 错误 | ✓ | ||
| 5 | 存在 | 匹配 | 错误 | ✓ | ||
| 6 | 存在 | 匹配 | 正确 | ✓ |
注意:组合 1 和 2 动作相同(都是 A2),可以合并;组合 3 和 4 动作相同,也可以合并。最终化简为 4 条用例。
步骤三:转化为可执行的测试用例
把判定表的每一列,写成一条完整的测试用例:
用例编号: TC-LOGIN-001
测试标题: 账号不存在时登录失败
前置条件: 使用一个未注册的账号
测试步骤:
1. 输入不存在的账号: "nonexist@test.com"
2. 输入任意密码: "123456"
3. 输入任意验证码: "abcd"
4. 点击「登录」按钮
预期结果: 页面提示「账号或密码错误」,停留在登录页
用例编号: TC-LOGIN-002
测试标题: 密码错误时登录失败
前置条件: 使用已注册的账号
测试步骤:
1. 输入已注册的账号: "user@test.com"
2. 输入错误密码: "wrongpass"
3. 输入任意验证码: "abcd"
4. 点击「登录」按钮
预期结果: 页面提示「账号或密码错误」,停留在登录页
用例编号: TC-LOGIN-003
测试标题: 验证码错误时登录失败
前置条件: 使用已注册的账号和正确密码
测试步骤:
1. 输入已注册的账号: "user@test.com"
2. 输入正确密码: "correctpass"
3. 输入错误验证码: "wrong"
4. 点击「登录」按钮
预期结果: 页面提示「验证码错误」,验证码刷新
用例编号: TC-LOGIN-004
测试标题: 所有信息正确时登录成功
前置条件: 使用已注册的账号和正确密码
测试步骤:
1. 输入已注册的账号: "user@test.com"
2. 输入正确密码: "correctpass"
3. 输入正确验证码: "a1b2"(以页面显示为准)
4. 点击「登录」按钮
预期结果: 登录成功,跳转到首页
4.5 判定表法的适用场景
不是所有功能都适合用判定表。我个人总结了几条经验:
| 适合用判定表 | 不适合用判定表 |
|---|---|
| 条件数量 3~6 个 | 条件超过 8 个(组合爆炸) |
| 每个条件取值有限(2~3 种) | 条件取值是连续值(如金额范围) |
| 业务逻辑有明确的「条件→动作」映射 | 业务逻辑依赖状态或时序 |
| 需要保证测试覆盖率 | 只需要冒烟测试 |
小技巧:条件超过 6 个时,我一般会先用「正交实验法」筛选组合,再用判定表细化。或者把大判定表拆成多个小判定表——比如先校验账号密码,再校验验证码,分两步走。
4.6 判定表法知识结构图
下面这张图帮你理清判定表法的整体脉络:
4.7 自动化执行中的判定表
判定表不光能用来设计用例,还能直接指导自动化脚本的编写。我习惯把判定表转成「数据驱动」的参数化数据:
# 判定表数据驱动示例(Python + pytest)
import pytest
# 判定表数据:每条用例是一个字典
login_test_data = [
{"account": "invalid", "password": "any", "captcha": "any",
"expected": "账号或密码错误"},
{"account": "valid", "password": "wrong", "captcha": "any",
"expected": "账号或密码错误"},
{"account": "valid", "password": "correct", "captcha": "wrong",
"expected": "验证码错误"},
{"account": "valid", "password": "correct", "captcha": "correct",
"expected": "登录成功"},
]
@pytest.mark.parametrize("data", login_test_data)
def test_login(data):
# 模拟登录操作
result = login_function(
account=data["account"],
password=data["password"],
captcha=data["captcha"]
)
assert result == data["expected"]
你看,判定表里的每一行,直接变成了一条参数化用例。维护起来也方便——业务逻辑变了,改判定表数据就行,代码不用动。
总结一下:判定表法是我在复杂业务逻辑场景下的首选方法。它强迫你把所有条件列清楚,再化简,最后生成用例。这个过程本身就是在帮你梳理业务逻辑——有时候画完判定表,你才发现原来产品经理的需求里藏着那么多「没说清楚」的地方。