| name | test |
| description | 当用户要求测试、验证、回归、跑测试,检查上次 agent 产出,或指定项目进行测试时使用;“测试一下”、
“验证 agent 产出”等说法也触发本技能。
|
| metadata | {"openclaw":{"emoji":"🧪"}} |
test — 系统化测试技能
执行前置
遵循当前目录 AGENTS.md「技能执行公共契约」;仅按需读取技能正文与 reference。
对目标项目执行可复现、证据驱动的系统化测试:解析测试对象(默认上次 agent 生成的工作,
可指定)、制定通过标准、逐项执行并保存全部证据;失败按 debug 循环修复、通过按 optim 循环优化;
支持设备切换(GPU/CPU/NPU)与多精度切换(默认单精度)。
核心原则
- 先定测试对象与通过标准,再执行:测试对象、测试项清单、每项预期与通过标准
必须在执行前确定;无法确定时先向用户提问(所有问题第一次交互一次性全部提出,用户一次回答),不臆断。
- 默认测试对象 = 上次 agent 生成的工作:从最近的
.agent.*.list(用户输入清单)
与 Git 最近提交/未提交改动推断工作内容与产物;用户可随时指定测试项目。
- 证据驱动:每个测试项记录触发命令、实际输出、退出码;通过/失败结论以实测为准,
不凭印象判断;统计数字必须实测。
- 证据先于断言(verification-before-completion):任何"通过/完成/修复"声明
必须基于本次会话刚运行的验证命令输出(退出码 0、0 失败、数值在容差内);
"应该能过""上次跑过""看起来没问题"均不构成证据;声明前逐项核对:
这个声明由哪个命令证明?运行了吗?输出确认了吗?未运行则先运行,跳过即视为未验证。
按声明闸门五步执行(吸收 superpowers verification-before-completion):
IDENTIFY(哪个命令证明此声明)→ RUN(完整运行)→ READ(读全输出、退出码、失败数)→
VERIFY(输出是否确认声明)→ ONLY THEN(附证据声明);任何一步跳过即视为未验证。
"通过"声明所需证据对照(需要 → 不充分):测试通过 → 本次 0 失败输出 → 上次跑过/应该能过;
bug 修复 → 原症状复现路径回归通过 → 改了代码/看起来没问题;
回归有效 → 红绿闭环(复现失败→修复通过→回退必失败→恢复通过) → 单次通过。
- 中间变量自行计算并保存:不省略中间步骤、不丢弃中间结果;所有中间变量
计算后立即落盘(可复现、可审查)。
- 全部结果落盘:中间结果、最终结果、数据图表统一保存到产物目录,路径与格式可追溯。
- 循环解决 bug:测试失败不停止——按 debug 方法论(复现→证据→根因→最小修复→回归)
循环直至全部通过或用户终止;每次迭代更新终端摘要。
- 循环优化:全部通过后审视优化空间(速度/资源/精度稳定性),按 optim 方法论
(测量基线→主导项→最小改动→复测)循环优化;每轮优化后必须回归全部测试;
收益微小且复杂度代价大时向用户报告权衡。
- 设备、精度与诚实性:设备探测后择优(CUDA GPU 优先),可显式切换 CPU/NPU;
默认单精度,可切换多精度;数据读写间显式管理精度转换(dtype 记录与转换规则)。
设备缺失、精度限制、测试未覆盖项如实报告;无法测试的项标注原因,绝不虚报"通过"。
触发时机
- 用户要求测试:"测试"、"test"、"验证"、"回归测试"、"跑测试"、"测试一下"
- 用户要求检查 agent 产出:"检查上次的工作"、"验证agent产出"、"测试上次生成的"、
"上次生成的脚本验证一下"
- 用户指定测试对象:"测试 bin/agent.sh"、"测试 09:16 会话的产物"、
"测试某个功能/脚本/程序"
- 与其他技能配合:测试失败定位/修复用 debug 技能,性能优化用 optim 技能,
改动审查用 diff 技能,生成测试报告可用 analy 技能,测试完成后打标签用 tag 技能;
多独立测试项(互不依赖的用例)→ dispatch 并行验证,整合后统一回归
测试对象解析
默认:上次 agent 生成的工作
按以下优先级推断(仅在当前工作目录内收集证据):
- 最近
.agent.*.list(用户输入清单,格式参考 .agent.*.list 最新一份):
ls -1t .agent.*.list 2>/dev/null | head -3
cat "$(ls -1t .agent.*.list 2>/dev/null | head -1)"
清单内每条用户输入即任务描述:上次任务做了什么、涉及哪些文件/功能,即默认测试对象。
2. Git 最近提交与工作树改动:
git log --oneline -5
git show --stat HEAD | head -30
综合以上证据形成测试对象清单(被测文件/功能 + 预期行为 + 通过标准),
在终端摘要中说明任务定义,并向用户输出确认。
无法确定时:一次性列出全部候选对象(最近清单/Git 提交或改动中出现的文件),向用户提问,不逐次追问。
用户指定测试项目
- 输入
{~test <对象>} 或直接说明("测试 bin/agent.sh"、"测试上次的优化改动"),
按用户指定执行;对象为具体文件/功能/改动区间(如 git commit/tag 区间)。
- 指定对象不在当前工作目录时:先向用户确认路径与访问权限(所有问题一次全部列出,用户一次回答),不越界访问。
设备与精度管理
设备探测与切换
nvidia-smi -L 2>/dev/null && nvidia-smi --query-gpu=name,memory.total --format=csv,noheader
python3 -c "import cupy; print('cupy', cupy.__version__, 'devices', cupy.cuda.runtime.getDeviceCount())" 2>/dev/null
python3 -c "import torch; print('torch', torch.__version__, 'cuda' if torch.cuda.is_available() else 'cpu')" 2>/dev/null
python3 -c "import torch_npu; print('torch_npu available')" 2>/dev/null || echo "NPU: not available"
nproc
- 选择优先级:CUDA GPU 可用 → 默认 GPU;无 GPU → CPU;NPU 探测到且可用 → 列为候选,
经用户确认后使用(NPU 生态不统一,不默认启用)。
- 切换方式:环境变量
TEST_DEVICE=cuda|cpu|npu(默认 cuda 可用则 cuda,否则 cpu),
或测试配置传入;设备选定后仅写入产物元数据。
- 设备差异记录:同一测试在 GPU/CPU 上分别运行的结果(如数值误差、耗时)对比保存,
注明设备型号。
多精度切换(默认单精度)
- 默认单精度 fp32;
TEST_PRECISION=fp32|fp64|fp16 切换(fp16 仅当设备支持时用,
注意数值范围与溢出风险)。
- 精度设置仅写入产物元数据(
dtype=float32 等)。
- fp64 仅 CPU/双精度 GPU 支持时可用;不支持时如实报告并回退 fp32。
数据读写间的精度转换
- 保存:每个数据文件记录 dtype(文件名后缀如
_fp32.npy,或伴随元数据 JSON);
- 读取:按目标精度转换(如
arr.astype(np.float32)),转换规则显式记录;
- 跨精度比较:使用相对容差(fp32 比较默认
rtol=1e-5, atol=1e-7;
fp64 可收紧;fp16 放宽),容差与比较结果一并记录;
- 中间变量:转换发生在每个中间变量计算后、保存前,保证读入精度与计算精度一致;
- 非数值项目(纯 shell/配置):设备与精度项标注"不适用(非数值项目)",跳过不报错。
工作流程
Step 1. 解析测试对象与通过标准
- 按「测试对象解析」确定测试对象(默认上次 agent 工作 / 用户指定);
- 确定通过标准:每项测试的预期输出/数值容差/行为断言;
- 输出一句任务定义(如"测试对象:bin/agent.sh(用户输入清单与 Git 检查点功能)"),
在终端摘要中说明;对象或标准不明确时立即向用户提问(所有问题一次全部列出,不逐次追问)。
Step 2. 环境与基线
git rev-parse --is-inside-work-tree && git rev-parse --abbrev-ref HEAD && git log -1 --oneline
bash -n <被测脚本>
- 记录测试对象文件清单与当前版本(git hash);
- 生成测试计划表(测试项编号、名称、触发命令、预期、通过标准),在终端摘要中说明。
Step 3. 执行测试
逐项执行测试计划;每个测试项:
- 运行触发命令,记录实际输出(过长截断并注明)与退出码
exit=N;
- 与预期对比,判定 通过 / 失败 / 跳过(附原因);
- 中间变量自行计算并保存到
test_out/intermediate/(含 dtype/设备标注),
保存记录在终端摘要中说明;
- 数值类测试记录比较容差与误差值。
Step 4. 失败处理(debug 循环)
存在失败项时,按 debug 技能方法论循环处理:
- 复现:用记录的触发命令稳定复现失败;
- 定位:证据驱动(报错文本、退出码、诊断输出、Git 变更)、二分收敛、不变量校验;
- 最小修复:只改根因所在行,遵循代码库既有约定;
- 回归:用原测试项复测,通过后跑全部测试;
- 循环直至全部通过或用户终止;每次迭代在终端摘要中说明
。
Step 5. 优化循环(全部通过后)
审视优化空间(执行速度、资源占用、精度稳定性),按 optim 技能方法论循环:
- 测量基线(3–5 次取中位数,记录原始值序列);
- 主导项分析(复杂度/调用开销/IO/启动),只优化主导项;
- 最小改动实现;改动后先回归全部测试,再复测对比;
- 循环直至目标达成、收益微小或用户终止;每轮迭代在终端摘要中说明;
- 优化收益量化对比(基线→优化后),如实记录,不虚报。
Step 6. 结果与图表保存
- 最终结果保存到
test_out/results/(含 dtype/设备标注与元数据);
- 数据图表生成到
test_out/figures/(如错误随迭代收敛图、GPU/CPU 性能对比图、
多精度误差对比图等);项目无图表需求时注明"无图表";
- 产物清单(文件 + 大小 + 格式)在终端摘要中说明。
Step 7. 总结(结构化输出)
✓ 测试完成
对象: <测试对象任务定义,如 bin/agent.sh 用户输入记录功能>
环境: <git 分支/HEAD> | <设备: cuda:0 RTX4090 / cpu / npu> | <精度: fp32>
计划: <N 项测试> 通过 <M> 失败 <K>(跳过 <S>: 原因)
debug: <N 次迭代>(修复: <文件:行号> <说明>,无则省略)
optim: <N 次迭代>(基线 → 优化后,收益量化,无则省略)
产物: test_out/intermediate/ (N 文件), test_out/results/ (N 文件), test_out/figures/ (N 图)
遗留: <未覆盖项/风险/待用户确认项,无则省略>
声明前自检(证据先于断言):输出上述"通过 M"前,逐项核对
M 个通过项均有本次会话的运行输出(退出码/数值)为证;缺失证据的项改为"未验证"或补跑后更新。
Step 8. 复查
- 关键结论回看原始输出核实(通过/失败统计、数值误差、产物存在性);
- 数值结果用不变量/守恒律/量纲校验(如总和守恒、对称性、极限行为)。
错误处理
| 场景 | 处理 |
|---|
| 测试对象无法确定 | 一次性列出全部候选(最近 .list/Git 提交或改动中的文件)提问确认,不逐次追问 |
无 .agent.*.list 且无 Git | 报告无证据,要求用户指定测试对象 |
| 指定对象不在工作目录 | 先向用户确认路径与访问权限(一次问全),不越界访问 |
| 无 GPU | 报告并 CPU 执行;注明精度限制(fp64 可用性等) |
| NPU 探测到但生态不熟 | 列为候选,经用户确认后使用 |
| 无 Python/CuPy/Torch | 报告;纯 shell 项目用 bash -n + 功能测试验证 |
| 测试失败 | 进入 debug 循环(复现→定位→最小修复→回归),循环直至成功或用户终止 |
| 多次 debug 迭代仍失败 | 检查证据是否不足或方向错误;向用户报告进展与下一步,不无限循环 |
| 优化收益微小 | 报告权衡(复杂度 vs 收益),由用户决定取舍 |
| fp16 溢出/精度不足 | 报告并回退 fp32;记录容差与误差 |
| 跨精度比较失败 | 核对容差设置与 dtype 转换路径,修正后重测 |
| 数据读写精度不一致 | 显式记录 dtype、统一转换规则(astype + 容差),复测 |
| 非数值项目 | 设备/精度项标注"不适用(非数值项目)",跳过不报错 |
| 产物目录已存在 | 时间戳/序号命名避免覆盖(如 test_out_2/),不覆盖已有产物 |
| 测试对象本身有 bug | 先 debug 修复再继续测试;Git 改动按公共契约检查,不自动提交或推送 |
注意事项
- 测试结论以实测为准(命令输出、退出码、数值误差),不虚报通过/失败与收益;
- 中间变量与中间结果必须保存,不省略中间步骤;
- 测试失败先 debug 定位根因再优化,不叠加盲改;
- 设备与精度选择、精度转换规则显式记录,保证测试可复现;