关于 smart-test
面向 Python 项目的测试技能,通过分析导入依赖和测试可靠性来选择受变更影响的测试。它提供从快速检查到完整套件的分级 pytest 策略,帮助开发者平衡迭代速度与覆盖范围。
主要功能
- 01Python 导入依赖映射
- 02直接与传递测试选择
- 03三级 pytest 策略
- 04按可靠性筛选快速测试
- 05YAML 映射与可靠性数据
适用场景
- 01为变更的 Python 文件选择测试
- 02提交前运行快速测试
- 03查找不稳定测试并安排调查
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ rysweet/ amplihack --skill smart-test安装后在 Claude Code 中输入/smart-test确认已加载。
附带文件README.md
详细介绍
智能测试选择技能
目的
根据代码变更智能选择要运行的测试,从而优化测试执行。无需每次都运行完整测试套件,此技能会:
- 使用导入依赖分析,将代码变更映射到受影响的测试文件
- 针对不同的反馈周期需求提供分级测试策略
- 跟踪测试可靠性,以便在快速运行中优先选择稳定的测试
何时激活
当你提到以下内容时,我会自动加载:
- “运行受影响的测试”或“运行受波及的测试”
- “智能测试”或“智能化测试”
- “应该运行哪些测试”或“测试选择”
- “快速测试”或“快速运行测试”
- “变更对应的测试”或“这个 PR 对应的测试”
核心概念
测试级别
第 1 级:快速测试(少于 1 分钟)
- 直接受影响的单元测试(导入了变更文件的测试)
- 仅运行高可靠性测试(不包括不稳定测试)
- 每次保存或提交前运行
- 命令:
pytest -m "not slow and not integration" [selected_tests]
第 2 级:受波及的测试(少于 5 分钟)
- 所有受变更影响的测试(直接依赖 + 传递依赖)
- 包含变更模块的集成测试
- 提交前或 PR 草稿阶段运行
- 命令:
pytest [selected_tests]
第 3 级:完整测试套件
- 完整测试套件
- 在 PR 准备好供审查或 CI 阶段运行
- 命令:
pytest
导入依赖分析
此技能通过分析 Python 导入来构建依赖图:
source_file.py
|
+-- Imported by: module_a.py, module_b.py
| |
| +-- Tested by: test_module_a.py, test_module_b.py
|
+-- Tested by: test_source_file.py (direct test)
直接测试:与模式 test_{module}.py 或 {module}_test.py 匹配的文件
间接测试:导入了导入变更文件的模块的测试
可靠性跟踪
根据可靠性为测试评分(0.0 到 1.0):
- 1.0:始终通过(稳定)
- 0.5-0.9:偶尔失败(需调查)
- < 0.5:频繁失败(不稳定——从第 1 级中排除)
可靠性记录在 ~/.amplihack/.claude/data/test-mapping/reliability.yaml
用法
分析变更并获取测试命令
User: What tests should I run for my changes?
Claude (using smart-test):
1. Analyzes git diff or staged changes
2. Maps changed files to test dependencies
3. Returns tiered test commands
Example Output:
------------------------------------------
Smart Test Analysis
------------------------------------------
Changed Files:
- src/amplihack/core/processor.py
- src/amplihack/utils/helpers.py
Tier 1 (Fast - 45s estimated):
pytest tests/unit/test_processor.py tests/unit/test_helpers.py -v
Tier 2 (Impacted - 3m estimated):
pytest tests/unit/test_processor.py tests/unit/test_helpers.py \
tests/integration/test_pipeline.py -v
Tier 3 (Full - 12m estimated):
pytest
Recommendation: Start with Tier 1 for quick feedback.
构建或刷新映射缓存
User: Build the test mapping for this project
Claude:
1. Scans all Python files
2. Builds import dependency graph
3. Maps source files to test files
4. Saves to .claude/data/test-mapping/code_to_tests.yaml
检查测试可靠性
User: Show flaky tests
Claude:
1. Reads reliability.yaml
2. Lists tests with reliability < 0.8
3. Suggests investigation or quarantine
流程
第 1 步:识别变更文件
# For staged changes
git diff --cached --name-only --diff-filter=ACMR
# For all uncommitted changes
git diff --name-only --diff-filter=ACMR
# For PR changes (vs main)
git diff main...HEAD --name-only --diff-filter=ACMR
仅筛选 Python 源文件(映射时排除测试文件)。
第 2 步:构建导入图
对于每个 Python 文件,提取导入:
# Patterns to detect:
import module
from module import item
from package.module import item
from . import relative
from ..parent import item
构建双向映射:
- 正向:文件 -> 它导入的内容
- 反向:文件 -> 导入它的内容
第 3 步:映射到测试
对于每个变更文件,通过以下方式查找测试:
- 直接匹配测试:
test_{filename}.py或{filename}_test.py - 基于导入:导入变更模块的测试
- 传递依赖:导入那些会导入变更模块的模块的测试(1 层)
第 4 步:应用可靠性筛选
仅对第 1 级,排除可靠性低于 0.8 的测试。
第 5 步:生成命令
输出带有相应标记的 pytest 命令:
# Tier 1
pytest -m "not slow and not integration" tests/a.py tests/b.py
# Tier 2
pytest tests/a.py tests/b.py tests/c.py
# Tier 3
pytest
数据存储
code_to_tests.yaml
# .claude/data/test-mapping/code_to_tests.yaml
version: 1
last_updated: "2025-11-25T10:00:00Z"
mappings:
src/amplihack/core/processor.py:
direct_tests:
- tests/unit/test_processor.py
indirect_tests:
- tests/integration/test_pipeline.py
transitive_tests:
- tests/e2e/test_full_workflow.py
src/amplihack/utils/helpers.py:
direct_tests:
- tests/unit/test_helpers.py
indirect_tests:
- tests/unit/test_processor.py # processor imports helpers
reliability.yaml
# .claude/data/test-mapping/reliability.yaml
version: 1
last_updated: "2025-11-25T10:00:00Z"
tests:
tests/unit/test_processor.py::test_basic:
passes: 98
failures: 2
reliability: 0.98
last_failure: "2025-11-20"
tests/integration/test_api.py::test_timeout:
passes: 45
failures: 15
reliability: 0.75
last_failure: "2025-11-24"
flaky_reason: "Network dependent"
与工作流集成
此技能与 DEFAULT_WORKFLOW.md 集成:
第 12 步:运行测试和提交前钩子
- 提交前使用第 1 级(快速测试)
- 快速反馈变更代码的情况
第 13 步:强制本地测试
- 提交前使用第 2 级(受波及的测试)
- 确保测试覆盖受影响的代码路径
CI 流水线
- 草稿 PR 使用第 2 级
- 准备好供审查的 PR 使用第 3 级(完整测试)
标记集成
可与 pyproject.toml 中已有的 pytest 标记配合使用:
slow- 第 1 级中排除integration- 第 1 级中排除e2e- 第 1 级和第 2 级中排除neo4j- 需要特殊环境requires_docker- 需要 Docker 守护进程
快速参考
| 场景 | 层级 | 时间预算 | 命令模式 |
|---|---|---|---|
| 提交前 | 1 | < 1 min | pytest -m "not slow" [affected] |
| 推送前 | 2 | < 5 min | pytest [affected + transitive] |
| 草稿 PR | 2 | < 5 min | pytest [affected + transitive] |
| PR 就绪 | 3 | 完整 | pytest |
| CI 主分支 | 3 | 完整 | pytest |
理念契合
极致简洁
- 简单的层级系统(1、2、3)
- 使用 YAML 存储,而非数据库
- 使用导入分析,而非复杂的 AST 解析
杜绝虚假宣传的实现
- 真实的 pytest 命令(可直接复制粘贴)
- 根据测试数量估算实际耗时
- 不使用占位数据或模拟可靠性评分
测试金字塔
- 第 1 层优先覆盖单元测试(60%)
- 第 2 层增加集成测试(30%)
- 第 3 层包含端到端测试(10%)
互补技能
- test-gap-analyzer:识别缺失的测试
- qa-team:创建端到端和一致性测试场景(支持
outside-in-testing别名) - tester agent:为缺口编写新测试
- pre-commit-diagnostic:修复提交前检查失败
常见模式
模式 1:快速迭代
[Developer makes small change]
Claude: Run affected tests (Tier 1)
[45 seconds later]
Claude: 3/3 tests passed. Ready for commit.
模式 2:推送前验证
[Developer about to push]
Claude: Run impacted tests (Tier 2)
[3 minutes later]
Claude: 12/12 tests passed including integrations.
模式 3:不稳定测试排查
User: Tests keep failing randomly
Claude: Checking reliability data...
Found 2 flaky tests (< 0.8 reliability):
- test_api_timeout (0.75) - Network dependent
- test_concurrent_write (0.68) - Race condition
Recommend: Quarantine these tests or fix root cause.
局限性
- 仅支持 Python 导入分析
- 仅进行单层传递分析(不包括更深层的依赖链)
- 可靠性数据需要先通过测试运行进行初始化
- 无法检测动态导入或基于字符串的导入
避免使用的情况
以下情况请勿使用 smart-test:
- 首次设置测试 - 尚无映射缓存;请先运行完整测试套件
- 大规模重构 - 模块结构发生重大变化时,映射会过时
- 配置变更 - 对
pytest.ini、conftest.py或测试固件的更改会影响所有测试 - CI 环境变量变更 - 可能需要重新运行所有依赖环境的测试
- 数据库架构迁移 - 应运行所有涉及数据库的测试
- 不稳定测试排查 - 运行完整测试套件以获取准确的可靠性数据
- 合并前最终检查 - 合并到主分支前务必运行第 3 层(完整测试套件)
经验法则:有疑问时,就运行完整测试套件。Smart-test 优化的是迭代速度,而非正确性。
错误处理与故障排除
常见问题
问题:“未找到变更文件对应的测试”
Cause: File is new or not yet mapped
Fix: Rebuild the mapping cache
User: "Rebuild test mapping cache"
问题:“导入分析失败”
Cause: Syntax error in Python file or circular imports
Fix: 1. Check file for syntax errors: python -m py_compile file.py
2. Resolve circular imports
3. Rebuild mapping cache
问题:“缺少可靠性数据”
Cause: No test runs have been recorded yet
Fix: Run full test suite once, then:
User: "Update test reliability with these results"
问题:“第 1 层测试耗时过长”
Cause: Too many tests marked as "fast" or slow tests not marked
Fix: 1. Add @pytest.mark.slow to tests > 1 second
2. Add @pytest.mark.integration to integration tests
3. Review test granularity
问题:“缓存已过期/选错测试”
Cause: Module structure changed since last cache build
Fix: Delete cache and rebuild:
rm -rf .claude/data/test-mapping/*.yaml
User: "Rebuild test mapping cache"
恢复命令
# Verify test mapping is valid
python -c "import yaml; yaml.safe_load(open('.claude/data/test-mapping/code_to_tests.yaml'))"
# Check reliability data
python -c "import yaml; print(yaml.safe_load(open('.claude/data/test-mapping/reliability.yaml')))"
# Force full suite (bypass smart-test)
pytest --ignore-glob='**/test_slow_*'
# Find tests with no source mapping (orphaned tests)
find tests -name "test_*.py" -exec basename {} \; | sort > /tmp/tests.txt
缓存维护
出现以下情况时应重建映射缓存:
- 添加了新的测试文件
- 模块结构发生重大变化
- 缓存已超过 7 天
手动触发:“重建测试映射缓存”
注意:从第 1 层开始,以便快速获得反馈。如果测试通过,通常就能发现回归问题。只有在接近提交/推送节点时,才升级到更高层级。