测
测试设计评审
作者:鹿Sir开发工具v1
基于 Farley 测试八特性与「同义反复剧场」检测,系统评估测试套件质量,输出加权 Farley 指数、逐项评分、反模式清单与改进建议。当用户要求「评审测试」「评估测试质量」「我的测试写得好不好」「测试设计审查」「检查测试套件」时触发。不适用于编写测试或常规代码审查。
下载量
428
点赞
106
价格
免费
技能文档
---
name: maroffo-test-design-reviewer
title: 测试设计评审
description: 基于 Farley 测试八特性与「同义反复剧场」检测,系统评估测试套件质量,输出加权 Farley 指数、逐项评分、反模式清单与改进建议。当用户要求「评审测试」「评估测试质量」「我的测试写得好不好」「测试设计审查」「检查测试套件」时触发。不适用于编写测试或常规代码审查。
category: 开发工具
---
# 测试设计评审(Test Design Reviewer)
## 质量要求
- 评分前必须完整阅读每一个测试文件
- 质量优先于速度:分析每个测试实际验证了什么
- 不可跳过「同义反复剧场」检测
## 技能工作流
### 步骤 1:收集测试文件
识别范围内的全部测试文件,按语言使用对应匹配模式:
- Go:`*_test.go`
- Python:`test_*.py`、`*_test.py`
- Ruby:`*_spec.rb`
- JS/TS:`*.test.ts`、`*.spec.ts`
### 步骤 2:按 Farley 八特性逐项评分
对整个测试套件,每个特性打 0-10 分,并给出证据。
| # | 特性 | 关键问题 | 危险信号 |
|---|------|----------|----------|
| 1 | **可理解(Understandable)** | 5 秒内能看出测的是什么吗? | 含糊命名、无 arrange/act/assert 结构、共享状态 |
| 2 | **可维护(Maintainable)** | 实现一改测试就挂吗? | 测私有方法、脆弱选择器、硬编码值 |
| 3 | **可重复(Repeatable)** | 任意顺序、任意机器、每次运行结果一致吗? | 依赖时间、文件系统、执行顺序、共享数据库状态 |
| 4 | **原子性(Atomic)** | 失败原因唯一吗? | 一个断言测多种行为、重 setup |
| 5 | **必要性(Necessary)** | 这个测试有存在价值吗? | 重复覆盖、测试框架/语言本身的行为 |
| 6 | **粒度(Granular)** | 能定位失败位置吗? | 粗粒度断言(`assert result`)、大杂烩测试 |
| 7 | **快速(Fast)** | 毫秒级完成吗? | 真实 HTTP 调用、sleep 等待、每测试全量建库 |
| 8 | **优先(First)** | 是否先于产品代码编写? | 测试结构照搬实现结构而非行为 |
**评分方法:**
- **静态评分**:对信号密度(负信号数/测试方法数、正信号数/测试方法数)做 sigmoid 归一化,得到每特性 0-10 分。确定性计算统一委托 `lib/cli_calculator.py`(JSON 输入、JSON 输出)。
- **LLM 评分**:按特性整体评估语义层面,聚焦静态分析覆盖不到的部分(命名质量、断言恰当性、同义反复剧场)。
- **融合**:`final_property_score = 0.60 × static_score + 0.40 × llm_score`
- **保守默认**:某特性未检测到任何信号时,默认 5.0 分(质量未知,而非质量良好)。
**逐特性评分锚点:**
| 特性 | 9-10 | 7-8 | 5-6 | 3-4 | 1-2 |
|------|------|-----|-----|-----|-----|
| 可理解 | 读起来像规格说明,不看实现即懂行为 | 基本清晰,偶有歧义 | 需读代码才能理解 | 含糊,依赖实现细节 | test1/test2 式命名,到处魔法数字 |
| 可维护 | 抽象得当,验证行为而非实现 | 分离良好,偶有脆弱点 | 部分实现耦合,mock 过度指定 | 强耦合,精确次数 verify | 反射取私有字段,逐行照搬实现 |
| 可重复 | 完全确定,无外部依赖 | 极少抖动,环境依赖少 | 偶发抖动,存在时序依赖 | 依赖文件系统/时序/环境 | sleep、文件 IO、网络、系统时间、未播种随机 |
| 原子性 | 完全隔离,可并行 | 基本隔离,少量共享 setup | 存在共享状态,顺序偶有影响 | 强互相依赖,必须按序执行 | 共享可变静态量,顺序注解 |
| 必要性 | 每个测试价值独特,参数化覆盖变体 | 多数有价值,少量冗余 | 打勾式测试,中度冗余 | 冗余测试,测框架行为,mock 同义反复 | assertTrue(true)、被禁用测试、只验证 mock |
| 粒度 | 单一结果,精确定位 | 聚焦,偶有逻辑断言组 | 多行为混合,定位费力 | 松散,多个不相关断言 | 20+ 断言,testEverything() |
| 快速 | 纯计算,无 IO,毫秒级 | 较快,有优化空间 | 部分慢测试,套件耗时明显 | 文件 IO 或数据库调用 | sleep、网络调用、重度 setup/teardown |
| 优先 | 测试先行证据明确,测试驱动设计 | 大概率先行,设计影响良好 | 不明确,测试像事后补充 | 照搬实现,疑似后补,mock 堆砌 | 明显事后编写,覆盖率补丁 |
**聚合方法:**
- **测试方法级**:逐方法收集信号
- **文件级**:正信号取均值,负信号取 P90(最差者必须暴露)
- **套件级**:按代码行数加权的跨文件均值
**大套件抽样:**
- 50 个测试文件以内:全量分析
- 超过 50 个:SHA-256 确定性抽样(30%),另加上超过 100 个测试方法的全部文件
**加权 Farley 指数** = `(U×1.5 + M×1.5 + R×1.25 + A×1.0 + N×1.0 + G×1.0 + F×0.75 + T×1.0) / 9.0`
分母是权重之和 9.0,不是特性数量 8。U/M 权重最高(可读性、耦合),F 权重最低(速度因场景而异)。
| 区间 | 评级 | 解读 |
|------|------|------|
| 9.0-10.0 | 标杆 | 示范级套件,测试即活文档 |
| 7.5-8.9 | 优秀 | 高质量,有少量改进空间 |
| 6.0-7.4 | 良好 | 基础扎实,改进点明确 |
| 4.5-5.9 | 一般 | 可用,但测试设计需重点投入 |
| 3.0-4.4 | 较差 | 测试价值有限,需大规模重构 |
| 0.0-2.9 | 危险 | 测试可能有害,考虑推倒重写 |
### 步骤 3:同义反复剧场检测
核心问题:**「把所有产品代码删光,这些测试还能通过吗?」**
扫描以下 4 种模式:
| 模式 | 特征 | 示例 |
|------|------|------|
| **Mock 同义反复** | 测试验证的是 mock 返回了被设置好的值 | `mock.return_value = 42; assert service.get() == 42`(只测了 mock) |
| **纯 Mock 测试** | 所有依赖全被 mock,没有任何真实代码执行 | 5 个 mock、0 个真实对象的测试 |
| **平凡同义反复** | 断言恒为真,与代码无关 | 函数签名保证返回 dict,却 `assert isinstance(result, dict)` |
| **框架测试** | 测的是框架行为而非应用逻辑 | 测框架校验规则是否生效、fixture 是否注入 |
同时扫描 **mock 交互反模式**(影响可维护分):
| 模式 | 特征 |
|------|------|
| **过度指定交互** | 精确调用次数 verify、调用顺序验证、verifyNoMoreInteractions |
| **测内部细节** | ArgumentCaptor 深挖参数、verify(never()) 逐分支复刻实现、verify 远多于 assert |
每个发现需报告:文件、行号、模式类型、为什么有问题。
### 步骤 4:输出报告
```markdown
## 测试设计评审报告
### Farley 指数:X.X / 10.0(评级)
| 特性 | 静态分 | LLM 分 | 融合分 | 权重 | 加权分 | 关键证据 |
|------|--------|--------|--------|------|--------|----------|
| 可理解 | X.X | X.X | X.X | 1.50x | X.XX | ... |
| 可维护 | X.X | X.X | X.X | 1.50x | X.XX | ... |
| 可重复 | X.X | X.X | X.X | 1.25x | X.XX | ... |
| 原子性 | X.X | X.X | X.X | 1.00x | X.XX | ... |
| 必要性 | X.X | X.X | X.X | 1.00x | X.XX | ... |
| 粒度 | X.X | X.X | X.X | 1.00x | X.XX | ... |
| 快速 | X.X | X.X | X.X | 0.75x | X.XX | ... |
| 优先(TDD) | X.X | X.X | X.X | 1.00x | X.XX | ... |
### 同义反复剧场分析
以下小节始终保留,无发现时写「未检测到」。
#### Mock 同义反复
| 测试方法 | 行号 | Mock 设置 | 断言 |
#### 纯 Mock 测试
| 测试方法 | 行号 | 证据 |
#### 平凡同义反复
| 测试方法 | 行号 | 断言 |
#### 框架测试
| 测试方法 | 行号 | 断言 | 实际测的是什么 |
**小结**:共 {total} 处,涉及 {affected}/{total_methods} 个测试方法。
### 改进建议 Top 3
1. [针对权重最高且得分最低特性的最高收益修复]
2. [第二优先级]
3. [第三优先级]
### 方法说明
- 静态/LLM 融合比例:60/40
- 分析文件数:{count}({抽样说明})
- 语言:{lang},框架:{framework}
```
## 确定性评分计算器
`lib/cli_calculator.py` 提供 JSON 输入、JSON 输出的确定性计算,所有 Farley 指数算术必须委托给它,避免模型手算舍入漂移。
可用子命令:`normalize-property`、`blend-scores`、`compute-farley`、`get-rating`、`aggregate-file`、`aggregate-suite`、`full-pipeline`。
```bash
# 从信号计数归一化单个特性得分
python lib/cli_calculator.py normalize-property '{"prop":"U","neg_count":2,"pos_count":8,"total_methods":20}'
# 由 8 个融合分计算 Farley 指数
python lib/cli_calculator.py compute-farley '{"U":8.5,"M":7.0,"R":9.0,"A":8.0,"N":7.5,"G":8.0,"F":6.0,"T":7.0}'
# 端到端:原始信号 + 可选 LLM 分 → 指数 + 评级
python lib/cli_calculator.py full-pipeline '{"properties":{"U":{"neg_count":2,"pos_count":8,"total_methods":20},...},"llm_scores":{"U":8.0,...}}'
```
## 常见问题
| 问题 | 处理方式 |
|------|----------|
| 找不到测试文件 | 检查匹配模式;部分项目使用非标准目录 |
| mock 多不等于差 | 测边界时用 mock 是合理的;只在 mock 取代全部真实逻辑时标记 |
| 不同测试类型得分差异大 | 混合套件时,单元测试与集成测试分开评分 |
| 存量套件得分低 | 聚焦 Top 3 改进建议,不要建议全量重写 |使用说明
# 测试设计评审 基于 Farley 测试八特性(可理解、可维护、可重复、原子性、必要性、粒度、快速、优先)对测试套件做系统化质量评估,自动检测「同义反复剧场」等无价值测试反模式,输出加权 Farley 指数(0-10)与改进建议。 ## 使用场景 - 评审某个项目/模块的测试套件质量 - 接手遗留代码时评估现有测试的价值 - 重构测试前定位最值得改进的问题 ## 用法示例 ```text 评审 tests/ 目录下的测试质量 我的测试写得好不好?帮我做个测试设计审查 ``` 评分计算由 `lib/cli_calculator.py` 确定性完成(JSON 输入/输出),避免主观打分漂移。 ## 输出内容 - Farley 指数与评级(标杆/优秀/良好/一般/较差/危险) - 八特性逐项评分与关键证据 - 同义反复剧场分析(Mock 同义反复、纯 Mock 测试、平凡同义反复、框架测试) - 改进建议 Top 3
支持平台:Qoder · QoderWork · Claude · Codex 等 AI 编程助手