1. 为什么正交表至今仍是测试用例设计的硬通货
做功能测试超过五年的同行大概都有体会:需求评审完,面对一个表单页面上七八个输入项,每个输入项又有三到五个取值,如果老老实实做全排列组合,用例数轻松破千。跑一轮回归动辄半天,维护成本高得离谱,而且大部分组合根本跑不出新问题。正交表就是在这种场景下被反复拿出来用的东西——它用数学上的均衡分散原则,从全组合里挑出一批“代表”,让任意两个因子的任意取值组合都至少出现一次。听起来很学术,但落到实际工作里,就是把上千条用例压到几十条,覆盖率还不掉。
Allpairs 就是干这件事的老牌工具。它不是什么新潮玩意儿,但胜在稳定、免费、命令行直接出结果,配合一个 Excel 或 CSV 输入文件就能跑。最近一两年 AI 辅助写用例的讨论多了起来,很多人开始把 Allpairs 和 Deepseek 这类大模型工具串起来用:前者负责组合裁剪,后者负责把裁剪后的组合翻译成可读的自然语言用例步骤。这个组合思路我觉得挺务实,既保留了正交表的严谨性,又省掉了手写用例描述的重复劳动。
这篇内容适合谁看?如果你正在做功能测试、接口测试,或者带团队做用例评审,手上有一堆参数组合要处理,那这套流程可以直接抄。如果你只是想了解正交表工具怎么落地,或者想知道 AI 在用例生成环节到底能帮上多少忙,也能从里面拿到可复现的步骤。我会把 Allpairs 的下载、配置、输入文件格式、命令行参数、结果解读全部拆开讲,再补上 Deepseek 联动的具体做法和踩过的坑。
2. Allpairs 工具获取与运行环境准备
2.1 工具来源与版本选择
Allpairs 最早是 James Bach 那一派测试人推起来的工具,原始版本是个 Perl 脚本,后来有人打包成了 Windows 下的 exe。现在网上能搜到的 allpairs 下载渠道比较杂,有个人博客挂的压缩包,也有 GitHub 上别人重新整理的仓库。我的建议是优先找带源码或者带说明文档的版本,别随便下那种来路不明的 exe——测试工具本身如果带毒,那玩笑就开大了。
实际用下来,Windows 平台最省事的还是那个经典的allpairs.exe,配合一个allpairs.pl或者直接单文件运行。如果你在 Linux 或者 macOS 上,可以直接用 Perl 跑源码版本,依赖就是系统自带的 Perl 解释器,基本不用额外装东西。我试过在 Ubuntu 上直接perl allpairs.pl input.txt > output.txt,跑得挺稳。
注意:下载 exe 之后先丢到 VirusTotal 或者本地杀软扫一遍,别嫌麻烦。测试工具经常需要读本地文件,权限给大了容易出问题。
2.2 运行环境与依赖检查
Windows 下双击 exe 如果闪退,大概率是缺了某个运行库,或者路径里有中文和空格。我习惯把 allpairs 相关文件放在一个纯英文、无空格的目录里,比如D:\tools\allpairs\。然后在同目录下建一个input.txt,用命令行进入该目录执行。这样路径问题基本可以排除。
如果你用的是源码版本,先确认 Perl 可用:
perl -v能打印出版本号就行。Windows 上如果没装 Perl,可以装一个 Strawberry Perl,安装过程一路默认即可,装完把perl加到 PATH 里。这个步骤看起来基础,但我见过不少人在这一步卡住,后面所有操作都无从谈起。
2.3 目录结构与文件约定
我习惯的目录结构是这样的:
allpairs/ ├── allpairs.exe ├── input.txt ├── output.txt └── readme.txtinput.txt是输入文件,output.txt是跑出来的结果。每次跑之前把 input 改好,输出重定向到 output,方便对比不同版本的组合结果。如果你要批量跑多个场景,可以按场景建子目录,每个子目录里放一套 input 和 output,避免文件互相覆盖。
3. 输入文件格式与参数配置详解
3.1 输入文件的基本语法
Allpairs 的输入文件格式其实很简单,就是一张表:第一行是因子名,后面每行是一个因子的所有取值。因子名和取值之间用制表符或者逗号分隔都行,但整个文件要保持一致。我一般用制表符,因为从 Excel 复制出来直接就是制表符分隔,省得再转。
举个例子,假设要测一个登录页面,因子有浏览器、操作系统、用户名长度、密码强度:
浏览器 操作系统 用户名长度 密码强度 Chrome Windows 短 弱 Firefox macOS 中 中 Edge Linux 长 强 Safari Android - -这里有个细节:如果某个因子的取值数量比其他因子少,可以用-占位,Allpairs 会把它当成一个特殊值处理。但更稳妥的做法是让所有因子的取值数量尽量接近,或者用空值补齐。我试过取值数量差异太大的情况,跑出来的组合数会偏多,裁剪效果打折扣。
3.2 因子与水平的取舍逻辑
正交表的核心是“因子”和“水平”。因子就是你要考察的变量,水平就是每个变量的取值。实际项目里,不是所有变量都值得放进正交表。我的经验是:优先放那些取值之间可能产生交互影响的因子。比如“浏览器”和“操作系统”经常一起影响渲染结果,那就放进去;“用户名长度”和“密码强度”如果业务上完全独立,其实可以拆成两个独立的用例集,没必要硬塞进一张表。
另一个坑是水平太多。一个因子如果有十个取值,正交表跑出来的组合数会明显上升。这时候可以考虑做等价类划分,把十个取值归成三到四类,再放进正交表。比如“用户名长度”可以归成“短(1-6)”“中(7-12)”“长(13+)”,这样既保留了边界覆盖,又控制了组合规模。
3.3 命令行参数与输出控制
Allpairs 的命令行参数不算多,但有几个很实用:
allpairs.exe input.txt > output.txt这是最基本的用法。如果你想让输出更易读,可以加-v或者--verbose,具体看版本。有些版本支持-o指定输出文件,那就写成:
allpairs.exe -o output.txt input.txt我实测下来,最稳的还是用重定向>,因为不同版本的参数支持不一致,重定向是 shell 层面的,跟工具本身无关。
输出结果一般分两部分:一部分是“计划表”,列出每一组要测的组合;另一部分是“因子覆盖统计”,告诉你哪些两两组合被覆盖了。计划表可以直接复制到 Excel 里,加一列“预期结果”,就是一份可执行的用例集。
提示:跑完先看覆盖统计,确认所有两两组合都覆盖到了。如果有没有覆盖的,说明输入文件格式有问题,或者因子水平设置不合理。
4. 从正交表到可执行用例的完整实操
4.1 场景拆解与因子提取
拿一个电商下单流程举例。假设我们要测“提交订单”这个功能,涉及的变量有:
- 商品类型:实物、虚拟、预售
- 收货地址:已保存、新填写、海外
- 支付方式:余额、银行卡、第三方
- 优惠券:无、满减、折扣
- 库存状态:充足、紧张、无货
五个因子,每个三到四个水平。全组合是 3×3×3×3×3=243 条。用 Allpairs 跑一下,大概能压到 15 到 20 条左右。这个压缩比在实际项目里非常可观。
提取因子的时候有个原则:只放那些会影响测试结果的变量。比如“用户等级”如果对下单流程没有分支影响,就不用放。放了反而增加组合数,稀释了真正重要的交互覆盖。
4.2 输入文件编写与校验
把上面的因子写成 input.txt:
商品类型 收货地址 支付方式 优惠券 库存状态 实物 已保存 余额 无 充足 虚拟 新填写 银行卡 满减 紧张 预售 海外 第三方 折扣 无货注意每行的取值数量要一致。如果某个因子只有两个取值,可以用-补到三个,或者直接留空。我一般用-,看起来整齐。
写完先自己扫一眼:有没有拼写错误?有没有重复取值?这些低级错误如果带进正交表,跑出来的结果会莫名其妙。我踩过一次坑,把“满减”写成了“满减 ”(后面多个空格),结果 Allpairs 把它当成两个不同的值,组合数直接翻倍。
4.3 执行命令与结果解读
在命令行里执行:
cd /d D:\tools\allpairs allpairs.exe input.txt > output.txt然后打开 output.txt,你会看到类似这样的内容:
计划表: 商品类型 收货地址 支付方式 优惠券 库存状态 实物 已保存 余额 无 充足 实物 新填写 银行卡 满减 紧张 虚拟 海外 第三方 折扣 无货 ...每一行就是一条用例。你可以直接在 Excel 里加两列:“步骤”和“预期结果”。步骤可以写成“选择商品类型为实物,收货地址为已保存,支付方式为余额,不使用优惠券,库存充足,提交订单”。预期结果根据业务规则填。
覆盖统计部分会列出所有两两组合的覆盖情况。如果看到某个组合标记为“未覆盖”,说明输入文件有问题,或者该组合在数学上无法被当前的正交表覆盖,需要调整因子水平。
4.4 用例后处理与导入测试管理平台
跑出来的计划表还是“组合”形态,不是最终用例。我一般会做三步后处理:
- 补全步骤描述:把每个因子的取值翻译成操作步骤。这一步可以手工写,也可以用脚本批量生成。
- 补充预期结果:根据业务规则,为每条组合写预期结果。有些组合的预期结果是相同的,可以合并。
- 导入测试管理平台:把整理好的用例导入 TestLink、禅道或者 Jira。导入前确认字段映射,别把“步骤”导到“备注”里去了。
如果你用的是 Playwright 或者 Selenium 做自动化,还可以把正交表输出的组合直接转成数据驱动测试的参数集。比如用 Python 读 output.txt,每一行生成一个测试用例对象,传给自动化脚本执行。这个思路我在多个项目里用过,回归效率提升很明显。
5. 联动 Deepseek 生成用例描述的实操方案
5.1 为什么要把 Allpairs 和 Deepseek 串起来
Allpairs 解决的是“测哪些组合”的问题,但它不负责写用例步骤和预期结果。传统做法是测试人员对着组合表一条条手写,几十条下来也很枯燥。Deepseek 这类大模型在自然语言生成上表现不错,把组合表喂给它,让它按模板输出用例描述,能省掉大量重复劳动。
这个联动不是必须的,但如果你手头用例量大、迭代频繁,用 AI 辅助确实能提速。关键是输入要给清楚,别指望模型自己猜业务规则。
5.2 调用 Deepseek API 的准备工作
Deepseek 提供 API 接口,可以按 token 计费调用。你需要先拿到 API Key,然后选一个支持的模型。调用方式跟主流大模型接口类似,用 HTTP POST 发 JSON 就行。Python 里可以用requests或者官方的 SDK。
一个最简调用示例:
import requests url = "https://api.deepseek.com/v1/chat/completions" headers = { "Authorization": "Bearer YOUR_API_KEY", "Content-Type": "application/json" } payload = { "model": "deepseek-chat", "messages": [ {"role": "system", "content": "你是一个测试用例生成助手。"}, {"role": "user", "content": "请根据以下组合生成测试用例步骤和预期结果:..."} ] } resp = requests.post(url, headers=headers, json=payload) print(resp.json())注意:API Key 不要硬编码在脚本里,放到环境变量或者配置文件里,避免泄露。
5.3 提示词设计与输出格式约束
直接让模型“生成用例”往往得到一堆废话。我的做法是给一个严格的输出模板,并在提示词里明确字段和格式。比如:
你是一个功能测试用例生成助手。请根据我提供的组合表,为每一行生成一条测试用例。 输出格式要求: - 用例标题:简洁描述测试场景 - 前置条件:列出执行该用例前需要满足的条件 - 测试步骤:编号列出,每步一个操作 - 预期结果:描述操作后的预期表现 组合表如下: 商品类型=实物,收货地址=已保存,支付方式=余额,优惠券=无,库存状态=充足 ...这样模型输出的内容结构统一,后续可以直接解析成表格或者导入测试平台。我试过不加格式约束,模型会自由发挥,有的用例写步骤,有的写场景描述,整理起来反而更费劲。
5.4 批量处理与结果校验
如果组合有几十条,不要一次性全塞给模型,容易超出上下文长度或者导致输出质量下降。我一般按每批 5 到 10 条切分,循环调用,把结果追加到一个列表里。每批之间加个短暂延时,避免触发频率限制。
模型输出的用例不能直接信。我通常会做两轮校验:第一轮人工扫一遍,看有没有明显不符合业务规则的;第二轮拿几条去实际跑一下,确认步骤可执行、预期结果准确。AI 生成的用例在边界条件上经常有遗漏,比如“库存无货”时应该提示什么错误码,模型可能编一个不存在的提示语。这些都要靠人工兜底。
6. 常见问题排查与避坑经验
6.1 Allpairs 运行报错与解决
| 问题现象 | 可能原因 | 解决方法 |
|---|---|---|
| 双击 exe 闪退 | 缺少运行库或路径含中文 | 放到纯英文路径,安装 VC++ 运行库 |
| 输出为空 | 输入文件编码不对 | 另存为 UTF-8 或 ANSI,避免 BOM |
| 组合数异常多 | 因子水平差异过大 | 做等价类划分,统一水平数量 |
| 覆盖统计有遗漏 | 输入文件有重复值或空格 | 检查每行取值,去除首尾空格 |
| 命令行提示找不到文件 | 路径未加引号或目录不对 | 用绝对路径,或先 cd 到目录 |
6.2 Deepseek 调用中的典型坑
- API Key 无效:检查是否复制完整,有没有多余空格。
- 返回内容截断:调大
max_tokens,或者减少单次输入的组合数。 - 输出格式不稳定:在提示词里加“必须严格按照以下格式输出”,并给一个示例。
- 模型编造业务规则:在提示词里附上业务规则摘要,别让模型自由发挥。
- 频率限制:批量调用时加
time.sleep(1),或者用异步请求控制并发。
6.3 正交表使用的经验心得
正交表不是万能的。它擅长覆盖两两组合,但对三因子以上的交互覆盖较弱。如果你的业务里存在“三个条件同时满足才触发”的逻辑,正交表可能会漏掉。这时候需要额外补充针对性的用例,或者用更强的组合策略。
另外,正交表跑出来的用例数量虽然少,但每条用例的执行成本可能不低。比如“海外地址+第三方支付+无货”这种组合,实际执行时需要准备海外账号、第三方支付环境、无货商品,成本很高。所以裁剪完之后,还要结合执行成本做一轮筛选,把高成本低价值的组合去掉。
提示:正交表适合回归测试和冒烟测试,不适合替代探索性测试。该手工探索的地方还是要手工探索。
7. 把工具链固化下来:从一次性脚本到可复用流程
我见过很多团队用 Allpairs 都是一次性的:这次项目跑一下,下次换个项目又重新折腾一遍。其实这套流程完全可以固化下来,变成团队的标准工具链。
我的做法是建一个test-design-kit目录,里面放:
allpairs/:工具本体和输入输出模板scripts/:Python 脚本,负责读组合表、调 Deepseek、生成用例、导出 Exceltemplates/:提示词模板、用例模板、导入模板README.md:操作说明和常见问题
每次新项目,复制一份目录,改 input.txt,跑脚本,十分钟内拿到一份可评审的用例集。这个效率提升在迭代频繁的项目里非常明显。
脚本部分我一般用 Python 写,因为生态全,处理 Excel 和调 API 都方便。核心逻辑就是:读 input.txt → 跑 allpairs → 解析 output.txt → 分批调 Deepseek → 合并结果 → 写 Excel。每一步都可以单独调试,出问题容易定位。
如果你想把脚本打包成 exe 发给不装 Python 的同事,可以用 PyInstaller:
pyinstaller --onefile generate_cases.py生成的 exe 在dist/目录下,双击就能跑。注意打包时把依赖的模板文件和配置文件一起带上,或者在脚本里用相对路径读取。
这套流程我用了快两年,从最初的手工复制粘贴,到现在的半自动化,最大的体会是:工具的价值不在于多先进,而在于能不能稳定地嵌入日常工作流。Allpairs 老归老,但它的输出格式稳定、命令行友好,配合脚本和 AI,能解决实际问题。Deepseek 这类模型在用例描述生成上确实省事,但前提是你把输入和格式约束做好,否则生成的内容还不如手写。
最后分享一个小技巧:跑完正交表之后,把输出结果按因子取值做一次透视,看看哪些取值的组合出现频率特别低。这些低频组合往往是边界场景,值得单独拎出来重点测。这个动作花不了几分钟,但经常能发现一些被忽略的角落。