组合测试法调研文档
Nobody has claimed this yet.
Assessment
- Difficulty
- 5/5
- Estimated time
- Over a week
- Newbie friendliness
- 35/100
- Issue type
- Documentation
- Clarity
- Mostly clear
- Activity status
- Stale
- Tech stack
- go
- Domain
- build-system, ci-cd, testing-qa
Research direction
Start by reviewing the proposed PICT model.txt example, the .llar/test-matrix.yml configuration, and the GenerateTestMatrix and RunPairwiseTests entry points described in the issue. Validate the pairwise-testing claims, constraints, coverage levels, and LLAR integration plan against the referenced PICT and NIST materials. Done means the research and implementation plan are documented with verified examples and clear next steps.
Written by the indexing model from the issue text.
Description
LLAR 构建矩阵配对测试设计
参考:Jacek Czerwonka (Microsoft), "Pairwise Testing in Real World", 2006
1. 问题背景
1.1 矩阵组合爆炸
总组合数 = 选项1个数 × 选项2个数 × ... × 选项n个数
示例:50 个选项,每个 2 种值
2⁵⁰ = 1,125,899,906,842,624 (约 1125 万亿)
全量测试不可行。
1.2 解决方案:配对测试 (Pairwise Testing)
配对测试基于一个关键观察:大多数缺陷由单个参数或两个参数的交互引起。
2. t-way 组合测试
2.1 核心概念
t-way 覆盖:确保任意 t 个参数的所有值组合至少被测试一次。
| 术语 | 含义 | 说明 |
|---|---|---|
| 1-way | 每个参数的每个值至少出现一次 | 最简单,用例最少 |
| 2-way | 任意两个参数的所有组合至少出现一次 | = 配对测试 (pairwise) |
| 3-way | 任意三个参数的所有组合至少出现一次 | 三元组测试 |
| N-way | 所有参数的所有组合 | = 全量测试(穷举) |
2.2 为什么有效:一个用例覆盖多个配对
示例:3 个参数 A, B, C 各有 2 个值
2-way 需要覆盖的配对:
- AB: (0,0), (0,1), (1,0), (1,1) — 4 个
- AC: (0,0), (0,1), (1,0), (1,1) — 4 个
- BC: (0,0), (0,1), (1,0), (1,1) — 4 个
关键洞察:一个测试用例可同时覆盖多个配对!
测试用例 (A=0, B=0, C=0) 同时覆盖:
- AB=(0,0) ✓
- AC=(0,0) ✓
- BC=(0,0) ✓
因此 4 个测试用例就能覆盖全部 12 个配对,而非 8 个全组合。
2.3 效率对比(PICT 论文 Figure 2)
| 场景 | 全组合 | 2-way (PICT) | 压缩比 |
|---|---|---|---|
| 3⁴ | 81 | 9 | 89% |
| 3¹³ | 159 万 | 18 | ~100% |
| 4¹⁵ × 3¹⁷ × 2²⁹ | 巨大 | 37 | ~100% |
| 2¹⁰⁰ | 2¹⁰⁰ | 15 | ~100% |
| 10²⁰ | 10²⁰ | 210 | ~100% |
2.4 简单示例
参数:
- arch: [x86_64, arm64]
- os: [linux, darwin]
- compiler: [gcc, clang]
全组合: 2 × 2 × 2 = 8 种
配对测试: 只需 4 种即可覆盖所有两两组合
| # | arch | os | compiler | 覆盖的配对 |
|---|---|---|---|---|
| 1 | x86_64 | linux | gcc | (arch,os), (arch,compiler), (os,compiler) |
| 2 | x86_64 | darwin | clang | (arch,os), (arch,compiler), (os,compiler) |
| 3 | arm64 | linux | clang | (arch,os), (arch,compiler), (os,compiler) |
| 4 | arm64 | darwin | gcc | (arch,os), (arch,compiler), (os,compiler) |
验证:每对参数的所有值组合都至少出现一次。
3. PICT 算法机制
PICT 自 2000 年起在 Microsoft 内部使用,设计目标:速度、易用性、可扩展性。
3.1 两阶段架构
┌─────────────┐ ┌─────────────┐
│ 准备阶段 │ ──▶ │ 生成阶段 │
│ Preparation │ │ Generation │
└─────────────┘ └─────────────┘
3.2 准备阶段:参数交互结构
对于参数 A={0,1}, B={0,1}, C={0,1,2},建立交互表:
AB AC BC
──── ──── ────
00 00 00
01 01 01
10 02 02
11 10 10
11 11
12 12
每个槽位状态:
- uncovered: 未覆盖(需要测试)
- covered: 已覆盖
- excluded: 排除(约束导致的无效组合)
3.3 生成阶段:贪心启发式算法
While 存在未覆盖的槽位:
创建新测试用例 r
If r 为空:
选择未覆盖槽位最多的参数交互
选取第一个未覆盖组合
Else:
选择能覆盖最多未覆盖组合的值
且不违反任何排除约束
将选中的值加入 r
标记相关槽位为 covered
特点:
- 确定性算法(相同输入产生相同输出)
- 局部最优(贪心策略)
- 不产生候选测试(比 AETG 更快)
4. NIST 研究结论
4.1 缺陷发现率
| 覆盖强度 | 缺陷发现率 | 说明 |
|---|---|---|
| 2-way | 70-90% | 配对测试 |
| 3-way | 90-95% | 三元组测试 |
| 4-way | 95-98% | 四元组测试 |
| 6-way | ~100% | NIST 观察到的最大交互度 |
4.2 关键结论
"Most failures are induced by single factor faults or by the joint combinatorial effect of two factors."
— NIST Combinatorial Testing Research
- 大多数缺陷由 1-2 个参数交互引起
- 实际观察到的最大交互度为 6
- 4-way 覆盖通常足以发现几乎所有缺陷
5. PICT 实用特性
论文核心贡献:让配对测试从理论变得实际可用。
5.1 约束 (Constraints)
问题:现实中参数并非独立,某些组合无效(如 msvc 只能在 Windows)。
解决:用 IF-THEN 规则排除无效组合。
IF [File system] = "FAT" THEN [Size] <= 4096;
IF [File system] = "FAT32" THEN [Size] <= 32000;
IF [compiler] = "msvc" THEN [os] = "windows";
机制:约束被转换为排除组合,在参数交互结构中标记为 excluded,生成时自动跳过。
5.2 混合强度 (Mixed-Strength)
问题:某些参数交互更"敏感",需要更高覆盖;但全局提高 t 会产生过多用例。
解决:对关键参数子集使用更高的 t。
A: 0, 1
B @ 3: 0, 1 # B, C, D 之间使用 3-way
C @ 3: 0, 1
D @ 3: 0, 1
E: 0, 1
效果:B, C, D 的所有三元组被覆盖,其他参数仍使用 2-way。
5.3 子模型 / 参数层次 (Sub-Modeling)
问题:环境参数(硬件、OS)切换成本高,希望尽量减少环境组合数。
解决:将参数分层,底层先组合,结果作为上层的一个"复合参数"。
# 输入参数
Type: Single, Spanned, Striped
Size: 10, 100, 1000
File system: FAT, FAT32, NTFS
# 环境参数(子模型)
{ Platform, CPUs, RAM } @ 2
效果:
- 无子模型:31 个测试,17 种环境组合
- 有子模型:54 个测试,仅 9 种环境组合
5.4 种子 (Seeding)
用途 1:确保"重要"组合一定出现在结果中。
# seed.txt - 必须包含的组合
Single 100 Quick NTFS 4096 Off
Mirror Slow FAT32 # 部分种子也可以
用途 2:模型变更时复用旧测试用例,减少硬件配置重建成本。
5.5 负值测试 (Negative Testing)
问题:需要测试无效输入,但多个无效值同时出现会导致输入掩盖(第一个错误阻止后续检测)。
解决:用 * 标记无效值,PICT 确保每个测试用例最多包含一个无效值。
A: *LessThanZero, Zero, GreaterThanZero
B: *LessThanZero, Zero, GreaterThanZero
输出:
Zero GreaterThanZero (正向测试)
*LessThanZero GreaterThanZero (负向测试 - 只有一个无效值)
Zero *LessThanZero (负向测试 - 只有一个无效值)
5.6 权重 (Weights)
问题:某些值更常用(如默认选项),希望测试更多涉及这些值。
解决:为值设置权重,影响选择优先级。
Type: Single (5), Spanned (2), Striped (2), Mirror (2), RAID-5 (1)
Format: Quick (5), Slow (1)
File system: FAT (1), FAT32 (1), NTFS (5)
Compression: On (1), Off (10)
注意:权重仅在覆盖效果相同时生效,不会牺牲覆盖率。
6. 应用于 LLAR 构建矩阵
6.1 具体示例
参数定义:
arch: x86_64, arm64
os: linux, darwin, windows
compiler: gcc, clang, msvc
shared: ON, OFF
全组合: 2 × 3 × 3 × 2 = 36 种
2-way 配对测试: 只需约 9 种
需要覆盖的配对
| 参数对 | 组合数 | 示例 |
|---|---|---|
| arch × os | 6 | x86_64-linux, arm64-darwin, ... |
| arch × compiler | 6 | x86_64-gcc, arm64-clang, ... |
| arch × shared | 4 | x86_64-ON, arm64-OFF, ... |
| os × compiler | 9 | linux-gcc, darwin-clang, windows-msvc, ... |
| os × shared | 6 | linux-ON, darwin-OFF, ... |
| compiler × shared | 6 | gcc-ON, clang-OFF, ... |
| 总计 | 37 |
配对测试结果
| # | arch | os | compiler | shared |
|---|---|---|---|---|
| 1 | x86_64 | linux | gcc | ON |
| 2 | x86_64 | darwin | clang | OFF |
| 3 | x86_64 | windows | msvc | ON |
| 4 | arm64 | linux | clang | OFF |
| 5 | arm64 | darwin | gcc | ON |
| 6 | arm64 | windows | msvc | OFF |
| 7 | x86_64 | linux | msvc | OFF |
| 8 | arm64 | darwin | clang | ON |
| 9 | x86_64 | windows | clang | OFF |
验证 os × compiler 覆盖:
linux-gcc ✓ (#1) darwin-gcc ✓ (#5) windows-gcc —
linux-clang ✓ (#4) darwin-clang ✓ (#2,#8) windows-clang ✓ (#9)
linux-msvc ✓ (#7) darwin-msvc — windows-msvc ✓ (#3,#6)
加入约束
IF [compiler] = "msvc" THEN [os] = "windows"; # msvc 只在 Windows
IF [os] = "darwin" THEN [compiler] <> "msvc"; # darwin 无 msvc
约束排除了无效组合(darwin-msvc、linux-msvc),配对数减少,最终 7-8 个用例即可。
效果对比
| 方案 | 测试数 | 压缩比 |
|---|---|---|
| 全组合 | 36 | — |
| 2-way(无约束) | 9-10 | 72% |
| 2-way(有约束) | 7-8 | 78% |
6.2 完整参数定义
LLAR 构建矩阵参数:
- arch: [x86_64, arm64, arm32, riscv64]
- os: [linux, darwin, windows, android]
- compiler: [gcc, clang, msvc]
- compiler_version: [11, 12, 13, 14, 15]
- lang: [c, cpp]
- shared: [ON, OFF]
- debug: [ON, OFF]
6.3 测试策略
graph TD
A["全量组合<br/>4×4×3×5×2×2×2 = 1920"] --> B{"配对测试"}
B --> C["2-way: ~30 组合<br/>覆盖 70-90% 缺陷"]
B --> D["3-way: ~100 组合<br/>覆盖 90-95% 缺陷"]
B --> E["4-way: ~300 组合<br/>覆盖 95-98% 缺陷"]
style C stroke:#32CD32,stroke-width:3px
style D stroke:#4169E1,stroke-width:3px
style E stroke:#FF8C00,stroke-width:3px
6.4 分层测试策略
| 层级 | 覆盖强度 | 测试数量 | 应用场景 |
|---|---|---|---|
| 基础 | 2-way | ~30 | 每次配方提交 |
| 标准 | 3-way | ~100 | 每日构建 |
| 完整 | 4-way | ~300 | 发布前测试 |
7. 工具选型
7.1 PICT (Microsoft)
优点:
- 开源,MIT 协议
- 支持约束、混合强度、子模型、种子、权重等高级特性
- 命令行工具,易于集成
- Microsoft 内部广泛使用,经过实战验证
使用示例:
# model.txt
arch: x86_64, arm64, arm32
os: linux, darwin, windows
compiler: gcc, clang, msvc
shared: ON, OFF
# 约束: msvc 只在 windows 上
IF [compiler] = "msvc" THEN [os] = "windows";
pict model.txt
输出:
arch os compiler shared
x86_64 linux gcc ON
arm64 darwin clang OFF
arm32 windows msvc ON
x86_64 darwin clang ON
...
7.2 ACTS (NIST)
优点:
- NIST 官方工具
- 支持更高覆盖强度
- 支持复杂约束
- Java 实现,跨平台
7.3 推荐选择
推荐 PICT:
- 更轻量,易于集成到 CI
- 满足 2-way 到 4-way 需求
- 活跃维护(Microsoft 官方)
8. 实施方案
8.1 配方测试流程
sequenceDiagram
participant M as 配方维护者
participant CI as CI 系统
participant P as PICT
participant B as 构建系统
M->>CI: 提交配方
CI->>P: 生成测试矩阵 (2-way)
P-->>CI: 30 个测试组合
loop 每个组合
CI->>B: 执行构建
B-->>CI: 构建结果
end
CI-->>M: 测试报告
8.2 配置文件设计
# .llar/test-matrix.yml
parameters:
arch: [x86_64, arm64]
os: [linux, darwin]
compiler: [gcc, clang]
shared: [ON, OFF]
constraints:
# clang 在 darwin 上优先
- if: { os: darwin }
then: { compiler: clang }
weight: high
coverage:
default: 2-way # 配方提交
nightly: 3-way # 每日构建
release: 4-way # 发布测试
8.3 集成到 LLAR
// 生成测试矩阵
func GenerateTestMatrix(params MatrixParams, strength int) []MatrixCombination {
// 调用 PICT 生成配对测试组合
model := generatePICTModel(params)
combinations := runPICT(model, strength)
return combinations
}
// 执行配对测试
func RunPairwiseTests(formula Formula, strength int) TestReport {
combinations := GenerateTestMatrix(formula.Matrix, strength)
var results []TestResult
for _, combo := range combinations {
result := buildAndTest(formula, combo)
results = append(results, result)
}
return generateReport(results)
}
9. 预期效果
9.1 测试效率
| 指标 | 全量测试 | 配对测试 (2-way) | 提升 |
|---|---|---|---|
| 测试用例数 | 1920 | 30 | 64x |
| 测试时间 | 32 小时 | 30 分钟 | 64x |
| 缺陷发现率 | 100% | 70-90% | 可接受 |
9.2 与惰性构建结合
配对测试 (预构建) → 覆盖 70-90% 常用组合
用户触发构建 → 覆盖剩余冷门组合
云端缓存 → 逐步扩大覆盖
10. 下一步
- 集成 PICT 到 LLAR CI
- 设计 test-matrix.yml 配置格式
- 实现测试报告生成
- 与现有惰性构建策略整合
11. 参考资料
- Jacek Czerwonka, "Pairwise Testing in Real World", Microsoft, 2006
- PICT - Microsoft
- NIST Combinatorial Testing
- NIST SP 800-142: Practical Combinatorial Testing
- All-pairs Testing - Wikipedia
- Dominant language
- Go
- Stars
- 5
- Forks
- 4
- Avg merge
- 2d 13h
- Merged PRs (30d)
- 22
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from xgo-dev/llar
-
proposal
Difficulty 5/5 Over a week Newbie friendliness 25/100
-
enhancement
Difficulty 5/5 Over a week Newbie friendliness 38/100
-
enhancement
Difficulty 5/5 Over a week Newbie friendliness 25/100
-
enhancement
Difficulty 5/5 Over a week Newbie friendliness 42/100
-
enhancement
Difficulty 5/5 Over a week Newbie friendliness 35/100
Similar issues
-
optimization optimization:agents-md-curator
Difficulty 2/5 1-3 hours Newbie friendliness 86/100
githubnext/gh-aw-cao#13143 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
blinklabs-io/bursa#904 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
yanet-platform/ipfw-go#129 ·
-
bug confmap/provider/googlesecretmanagerprovider needs triage
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
open-telemetry/opentelemetry-collector-contrib#51273 · 2 comments ·
-
bug: AI Gateway client filter lists "Unknown" twice when NULL and literal Unknown clients coexist Openbug
Difficulty 2/5 1-3 hours Newbie friendliness 90/100