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 判定表法知识结构图

下面这张图帮你理清判定表法的整体脉络:

判定表法知识结构图 判定表法知识结构图 判定表法 条件桩 动作桩 条件项 动作项 核心步骤:列出条件 → 全排列 → 化简 → 生成用例 化简原则 合并「动作相同」且「条件无关」的列 适用场景 条件 3~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"]

你看,判定表里的每一行,直接变成了一条参数化用例。维护起来也方便——业务逻辑变了,改判定表数据就行,代码不用动。

总结一下:判定表法是我在复杂业务逻辑场景下的首选方法。它强迫你把所有条件列清楚,再化简,最后生成用例。这个过程本身就是在帮你梳理业务逻辑——有时候画完判定表,你才发现原来产品经理的需求里藏着那么多「没说清楚」的地方。