mcpField
S
smart-test

smart-test

github.com/rysweet测试与质量76133 次安装21 周前更新
代码仓库

关于 smart-test

面向 Python 项目的测试技能,通过分析导入依赖和测试可靠性来选择受变更影响的测试。它提供从快速检查到完整套件的分级 pytest 策略,帮助开发者平衡迭代速度与覆盖范围。

主要功能

  1. 01Python 导入依赖映射
  2. 02直接与传递测试选择
  3. 03三级 pytest 策略
  4. 04按可靠性筛选快速测试
  5. 05YAML 映射与可靠性数据

适用场景

  1. 01为变更的 Python 文件选择测试
  2. 02提交前运行快速测试
  3. 03查找不稳定测试并安排调查

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/rysweet/amplihack --skill smart-test

安装后在 Claude Code 中输入/smart-test确认已加载。

附带文件README.md

详细介绍

智能测试选择技能

目的

根据代码变更智能选择要运行的测试,从而优化测试执行。无需每次都运行完整测试套件,此技能会:

  1. 使用导入依赖分析,将代码变更映射到受影响的测试文件
  2. 针对不同的反馈周期需求提供分级测试策略
  3. 跟踪测试可靠性,以便在快速运行中优先选择稳定的测试

何时激活

当你提到以下内容时,我会自动加载:

  • “运行受影响的测试”或“运行受波及的测试”
  • “智能测试”或“智能化测试”
  • “应该运行哪些测试”或“测试选择”
  • “快速测试”或“快速运行测试”
  • “变更对应的测试”或“这个 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 步:映射到测试

对于每个变更文件,通过以下方式查找测试:

  1. 直接匹配测试:test_{filename}.py 或 {filename}_test.py
  2. 基于导入:导入变更模块的测试
  3. 传递依赖:导入那些会导入变更模块的模块的测试(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 minpytest -m "not slow" [affected]
推送前2< 5 minpytest [affected + transitive]
草稿 PR2< 5 minpytest [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:

  1. 首次设置测试 - 尚无映射缓存;请先运行完整测试套件
  2. 大规模重构 - 模块结构发生重大变化时,映射会过时
  3. 配置变更 - 对 pytest.ini、conftest.py 或测试固件的更改会影响所有测试
  4. CI 环境变量变更 - 可能需要重新运行所有依赖环境的测试
  5. 数据库架构迁移 - 应运行所有涉及数据库的测试
  6. 不稳定测试排查 - 运行完整测试套件以获取准确的可靠性数据
  7. 合并前最终检查 - 合并到主分支前务必运行第 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 层开始,以便快速获得反馈。如果测试通过,通常就能发现回归问题。只有在接近提交/推送节点时,才升级到更高层级。

评论

支持 Markdown