Treeify 专注把测试设计变成可建模、可评审、可持续迭代的过程——用结构化方法把问题空间拆开,再生成更少但更有覆盖的用例。

想一起把测试设计做得更工程化,欢迎来共创/内测。

添加 V:【TreeifyAI】进内测共创群,获得 Treeify 内测资格 / 免费 credits / MCP Server 试用

当测试维度不断叠加(设备 × 浏览器 × 角色 × 支付方式 × 语言 …),组合数量会迅速膨胀到难以管理。
配对测试(Pairwise,t=2)通过“覆盖所有成对组合至少一次”的原则,让你用较少的测试数量,获得尽可能多的交互覆盖。必要时可以提升到三元组合(t=3)。

1. 本文解决什么问题

这份文档主要面向两类读者:

  • 测试新手:面对大量组合,不知道如何系统地挑选测试用例。
  • 有经验的测试工程师:希望用一套可复用的方法,控制组合规模,同时维持较高覆盖。

阅读后,你会理解并能够实践:

  • 如何用配对/组合技术,从“所有可能组合”中提炼出一个精简但有质量的测试集。
  • 如何设计因素、水平、约束、种子用例和权重。
  • 如何把组合测试结果交付为“可审查、可追溯、可复用”的测试资产。
  • 如何在真实场景中使用:UI 组合矩阵、API 参数组合等。

2. 核心概念

2.1 因素与水平

  • 因素(Factor) :一个独立维度,例如:设备、浏览器、角色、支付方式。

  • 水平(Level) :某个因素的具体取值,例如:

    • 设备:iOS / Android / Desktop
    • 浏览器:Safari / Chrome / Firefox

在设计组合前,需要先把每个因素的取值明确列出来,尽量避免模糊表达(如“移动端”这种模糊类目,最好拆成 iOS 与 Android)。


2.2 配对测试(Pairwise,t=2)

  • 目标:生成一组测试用例,使所有“跨因素的成对水平组合”至少出现一次。
  • 好处:在大幅减少组合数量的前提下,仍能覆盖大部分具有代表性的交互问题。

可以简单理解为:

我不测试所有组合,但保证任何两个因素的任意取值至少在某个用例里“见过一次面”。


2.3 三元组测试(t=3)

  • 对所有“三个因素的组合(t=3)”做类似覆盖。
  • 成本更高,适合对风险较高、交互复杂的区域(例如:设备 × 浏览器 × 支付方式)使用。
  • 一般不会对所有因素都上 t=3,而是对关键子集(例如 3–4 个关键因素)使用。

2.4 约束(Constraints)

用来排除不可能或无意义的组合,例如:

  • Android × Safari 在实际产品中不存在。
  • 某些支付方式在特定地区不可用。

约束越清晰,生成结果越贴近真实业务,也减少浪费测试资源在“不会发生的组合”上。


2.5 种子 / 必含用例(Seeds)

业务上必须包含的测试组合,例如:

  • “会员 × 退款 × 中文语言”是曾经出过事故的组合。
  • 新上线的某个支付渠道 + 某个地区,需要重点回归。

这些种子用例可以在生成器运行前先固定,确保不会被“简化过程”意外删掉。


2.6 权重(Weights)

对一些更高风险或更重要的组合增加权重,例如:

  • 新增支付方式 × 特定地区。
  • 特定浏览器 × 特定设备,是主要用户群。

权重常用在更高级的生成工具中,目的是让生成器优先覆盖高风险交互,即便整体组合数量被压缩。


3. 适用与不适用场景

3.1 适用场景

配对/组合测试适合“多维度组合,但单条用例本身比较独立”的场景,例如:

  • UI 组合矩阵

    • 设备 × 浏览器 × 角色 × 语言
  • API 参数组合

    • 排序字段 × 排序方向 × page_size × filter
  • 功能开关 / 配置组合

    • 多个 feature flag / AB 实验组合
  • 兼容性测试

    • 不同 OS / 浏览器 / 网络条件 / 本地化设置的组合

关键特征是:每个组合都代表同一业务流程下的一次“配置变化” ,而不是复杂时序。


3.2 不适合单独使用的场景

配对测试并不是万能的,以下问题不宜仅依赖配对:

  • 强时序依赖:状态机、流程、审批链 → 更适合用状态模型或场景建模。
  • 数值边界 / 格式问题:输入范围、格式、单位 → 使用边界值 / 等价类。
  • 并发类问题:锁、冲突、事务 → 更需要专门的并发与一致性测试。
  • 高度依赖上下文的业务流程:例如复杂工作流多个步骤间有强依赖。

这类场景可以把配对测试当作补充,而不是主力方法。


4. 配对测试 8 步操作流程

这一节是可直接落地的“操作说明书”,做一遍之后基本就能掌握套路。

第 1 步:列出因素与水平

从 PRD / 现有实现 / 业务访谈中提取维度,并明确每个维度的取值。

示例:

  • 设备:iOS / Android / Desktop
  • 浏览器:Safari / Chrome / Firefox

注意:要把“模糊的分类”拆开,例如“Mobile”拆解成 iOS/Android,而不是直接当作一个单独水平。


第 2 步:写出约束

排除技术上或业务上不可能的组合。

示例:

NOT (Device = Android AND Browser = Safari)

在复杂业务中,也可以写成一组规则化表达,方便维护和自动生成。


第 3 步:选择强度(t)

  • 一般场景:t = 2(Pairwise) 已能带来明显收益。
  • 对交互复杂、事故成本高的领域(支付、结算、风控):可以对关键因素子集使用 t = 3。

不要一上来就把所有因素都设成 t=3,否则组合量会变得很难控制。


第 4 步:添加种子用例

根据历史缺陷、业务经验、上线风险,挑选必须包含的组合,例如:

  • “会员 × PayPal × 法语”
  • “Desktop × Chrome × 高价值用户 × 特定地区”

这些种子用例会被直接纳入最终集合,生成器在此基础上再补齐缺失的组合。


第 5 步:生成最小用例集合

使用工具或脚本进行生成:

  • 输入:因素、水平、约束、种子用例。
  • 输出:满足配对约束的最小(或接近最小)用例集。

这里不一定要追求绝对最优解,可读性和可维护性同样重要。对很多团队来说,一个略大但易理解的集合,往往比一个压到极限的“数学最优解”更好用。


第 6 步:分开处理无效 / 非法输入

一个常见错误是:把非法输入(格式错误、越界值)也当作“水平”塞进去,这会让生成器产出大量实际不会被执行的组合。

建议:

  • 组合生成器只负责有效组合。
  • 非法输入由边界值/等价类用例单独覆盖。
  • 需要时,可对某个组合同时设计“合法输入用例 + 非法输入用例”,但这属于测试设计过程,而不是生成器负责的部分。

第 7 步:在选定用例中叠加边界值

生成的组合通常只规定“维度”,没有规定“字段具体输入值”。

例如:

  • “iOS × Safari × Member × PayPal × fr-FR” 这条用例,可以选择使用“最大长度优惠码”、“最小订单金额”等边界值来提高该用例的价值。

做法是:

  • 在覆盖矩阵中标记哪些用例被“叠加了边界测试”。
  • 让少量组合同时承担“交互覆盖 + 边界覆盖”的责任。

第 8 步:产出覆盖矩阵

组合生成完成后,建议做一张简易的覆盖矩阵,用来说明:

  • 每个用例覆盖了哪些关键配对(或三元组)。
  • 是否所有关键配对都得到覆盖。

这张矩阵可用于:

  • 代码评审/测试评审时快速说明“我们测试到了什么”。
  • 复盘时回看哪些组合仍未覆盖。

5. 实例 A:UI 结账矩阵

5.1 因素与水平

因素水平
设备iOS, Android, Desktop
浏览器Safari, Chrome, Firefox
角色Guest, Member
支付方式Card, PayPal
本地化en-US, fr-FR

这里如果后续要增加更多水平(例如更多语言、更多支付渠道),也可以在同一结构下扩展。


5.2 约束

NOT (Device = Android AND Browser = Safari)

意味着生成器不会生成 Android + Safari 这种组合,因为产品中本身就不支持。


5.3 示例生成结果(12 条用例)

下面是一组可行的 Pairwise 结果示例(并非唯一解)。实际生成时,只需满足“所有成对组合至少出现一次”:

用例设备浏览器角色支付本地化
C01iOSSafariGuestCarden-US
C02iOSChromeMemberPayPalfr-FR
C03iOSFirefoxGuestPayPalfr-FR
C04AndroidChromeGuestCardfr-FR
C05AndroidFirefoxMemberCarden-US
C06DesktopSafariMemberCardfr-FR
C07DesktopChromeGuestPayPalen-US
C08DesktopFirefoxMemberPayPalfr-FR
C09iOSSafariMemberPayPalen-US
C10AndroidChromeMemberPayPalen-US
C11DesktopChromeMemberCardfr-FR
C12iOSFirefoxMemberCarden-US

实际项目中,你可以根据生成工具输出调整顺序、补充备注,不必与以上示例一模一样。


5.4 使用建议

  • 可以挑几条用例叠加“业务边界”,例如:

    • 在 C09 中使用最大长度优惠码 + 最低订单金额。
    • 在 C07 中使用特殊字符用户名。
  • 为每条用例定义验证点(oracles):

    • 页面渲染正常、关键功能可用。
    • 支付流程正常完成(或被正确拒绝)。
    • 日志中记录设备/浏览器/角色等维度信息。

5.5 风险加权建议

若某些因素组合的历史缺陷较多,例如“移动端支付 × 某浏览器”:

  • 在生成器中提高这类组合的权重;
  • 或者在生成结果中标记“高优先级测试”,安排在回归集前半部分执行。

6. 实例 B:API 查询参数组合

6.1 因素与水平

因素水平
sort_bycreated_at, price
orderasc, desc
page_size10, 50
filternone, in_stock
includenone, relations

这些因素构成了一个典型的列表查询接口参数空间。


6.2 约束

在本示例中:

  • include=relations 时,要求 page_size <= 50,而我们的取值本身已满足,不需要额外约束。
  • 若真实业务中有更严格限制,可显式写出约束规则。

6.3 示例生成结果(8 条)

用例sort_byorderpage_sizefilterinclude
A01created_atasc10nonenone
A02created_atdesc50in_stockrelations
A03priceasc50nonerelations
A04pricedesc10in_stocknone
A05created_atasc50in_stocknone
A06pricedesc50nonenone
A07created_atdesc10nonerelations
A08priceasc10in_stocknone

同样,这只是一个示例解。你可以用任何工具生成自己的组合,只要保证覆盖要求即可。


6.4 建议检查点(Oracles)

对每个组合,建议至少验证:

  • 排序

    • 主要排序字段是否正确;
    • 若存在相同 created_at,是否有稳定次级排序(例如 id)。
  • 响应契约

    • 字段结构是否符合接口 schema;
    • 当 include=relations 时,关联实体是否以约定方式返回。
  • 性能

    • page_size=50 时,响应时间是否满足 p95 指标。
  • 日志证据

    • 请求参数是否完整记录在日志 / trace 中(便于线上排查)。

7. 何时使用 t=3(三元组合)

在大多数业务中,t=2 的配对测试已经能够发现相当比例的交互问题。但在以下场景,可以考虑对部分因素使用 t=3:

  • 多层级功能开关组合:

    • 如 FeatureA × FeatureB × FeatureC 决定某个核心功能是否可用。
  • 多维兼容热点:

    • 设备 × 浏览器 × 语言 三者同时对渲染产生影响。
  • 风控/计费逻辑:

    • 客户类型 × 产品类型 × 地区 的组合影响费率或限额。

建议做法:

  • 不要对所有因素一刀切使用 t=3。
  • 先从风险视角挑选 3–4 个关键因素,对它们进行三元组合覆盖。
  • 其他因素保持 t=2 或单维度覆盖即可。

8. 评审要点(质量闸口)

在评审一个组合测试设计时,可以用下面的清单做简单闸口:

  • 因素与水平已列全,且描述规范、无模糊概念。
  • 约束明确,避免生成不可能存在的组合。
  • 已根据风险合理选择 t=2 或 t=3(而不是默认全用 t=3)。
  • 种子用例覆盖关键业务路径和历史缺陷路径。
  • 生成集合规模合理(既不过大,也不明显不足)。
  • 至少在部分用例中叠加了边界内容(长度/金额/日期等)。
  • 对每条用例都定义了清晰的验证点(oracles)和日志证据。
  • 有一份覆盖矩阵或说明,能看出成对(或三元)组合是否已全覆盖。

9. 常见误区

在实际项目中,配对测试常见的误用方式包括:

  • 用 pairwise 替代边界测试

    • 配对测试解决的是“组合覆盖”,不能取代边界值/等价类。
    • 建议先完成输入边界设计,再用配对测试选组合。
  • 没有约束

    • 不写约束会让生成器产生大量业务上不成立的组合,浪费时间。
  • 混入非法输入

    • 非法输入应该由边界值/等价类专门覆盖,而不是当作组合的一个水平。
  • 水平过度细化

    • 把每个浏览器版本、每个语言地区都当一个水平,组合量会非常大。
    • 建议按业务风险进行分组,例如“主流浏览器”、“次要浏览器”等。
  • 试图用 pairwise 找出时序问题

    • 配对测试对“静态组合”非常有用,但对涉及状态和时序的缺陷效果有限,应结合状态模型和流程测试一起使用。

10. 可复用模板:组合测试设计文档

# 组合测试设计 — <模块名>

## 1. 因素与水平
- 因素 A:a1 / a2 / …
- 因素 B:b1 / b2 / …
- 因素 C:c1 / c2 / …
- …

## 2. 约束
- NOT (A = a2 AND B = b1)
- NOT (Device = Android AND Browser = Safari)
- …

## 3. 强度选择
- 使用 t = 2(pairwise);如需覆盖三元交互则使用 t = 3,并限定在关键因素子集上。

## 4. 种子用例
| id  | A  | B  | C  | 备注              |
|-----|----|----|----|-------------------|
| S01 | …  | …  | …  | 历史缺陷路径      |
| S02 | …  | …  | …  | 核心业务路径      |

## 5. 生成结果
| id  | A  | B  | C  | D  | … |
|-----|----|----|----|----|---|
| T01 |    |    |    |    |   |
| T02 |    |    |    |    |   |
| …   |    |    |    |    |   |

## 6. 边界值叠加说明
- 在 T03 使用最大长度字段 X = …
- 在 T07 使用最小金额 Y = …
- 在 T09 使用跨时区日期边界 …

## 7. 覆盖矩阵(示意)
- 说明每个关键成对/三元组合由哪些用例覆盖。
- 例如:Device × Payment,列出组合 → Txx 用例 ID。

## 8. 检查点(Oracles)
- 业务结果:是否接受/拒绝、价格计算是否正确。
- API 契约:响应结构、错误码。
- 日志/监控:是否记录 device、browser、locale、rule_id 等字段。

11. 新手行动路径

10 分钟:快速入门

  • 选一个你最熟悉的业务功能(例如:结账页、登录页)。
  • 列出 3 个因素,每个因素 2–3 个水平。
  • 手工列出全部成对组合,并尝试压缩成 6–10 条用例,保证每个成对组合至少出现一次。
Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐