mcpField
S
sc-test

sc-test

github.com/tony363测试与质量2094 次安装30 周前更新
代码仓库

关于 sc-test

sc-test 是用于测试执行与覆盖率改进的技能,面向需要分析测试缺口并逐步补充测试的开发工作。它结合覆盖率报告、交互式优先级确认、按项目约定生成测试和复查结果。

主要功能

  1. 01运行不同类型的测试
  2. 02生成覆盖率报告
  3. 03定位并排序覆盖缺口
  4. 04按项目模式生成测试
  5. 05复跑测试并比较覆盖率

适用场景

  1. 01查找覆盖率不足的文件
  2. 02按优先级补充单元或集成测试
  3. 03验证新增测试并检查覆盖率变化

MCP 相关

可调用 PAL MCP 工具分析测试失败、审查测试质量并查阅框架文档;也可通过 Rube MCP 搜索测试报告集成、发送通知或处理结果。

安装

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

$npx skills add https://github.com/tony363/superclaude --skill sc-test

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

附带文件IMPORT_NOTES.md

详细介绍

测试与覆盖率技能

执行测试并进行覆盖率分析、交互式缺口识别、测试生成和迭代式覆盖率提升。

快速开始

# Run all tests
/sc:test

# Unit tests with coverage
/sc:test src/components --type unit --coverage

# Coverage gap analysis - identify untested code
/sc:test --gap-analysis --target 80

# Generate missing tests to reach target coverage
/sc:test --generate --target 80 --module src/services

# Watch mode with auto-fix
/sc:test --watch --fix

# Fix existing failures before adding coverage
/sc:test --fix-first --generate --target 80

# Web search for testing guidance (uses Rube MCP's LINKUP_SEARCH)
/sc:test --linkup --query "pytest asyncio best practices"

理念:尽早询问,频繁确认

此技能会在决策点灵活使用 AskUserQuestion。 测试覆盖率需要在速度与全面性之间权衡。请确认优先级,而不是猜测用户希望覆盖哪些内容。

  • 编写测试之前——确认优先处理哪些模块
  • 缺口较大时——询问应优先将精力放在哪里
  • 源代码看起来有缺陷时——在修复还是仅测试之间做出选择前先询问
  • 覆盖率运行结束后——询问是继续迭代还是停止

行为流程

  1. 发现 - 使用运行器模式对测试进行分类
  2. 配置 - 设置测试环境和参数
  3. 执行 - 运行测试并实时跟踪进度
  4. 分析 - 生成覆盖率报告和诊断信息
  5. 确认优先级 - 交互式检查点:询问用户要处理哪些内容
  6. 研究模式 - 阅读测试基础设施和现有惯例
  7. 生成 - 按照项目惯例编写缺失的测试
  8. 验证 - 运行新测试、修复失败项并执行 lint
  9. 核实覆盖率 - 重新运行覆盖率并比较前后结果
  10. 迭代 - 询问用户:继续、停止或更改重点
  11. 报告 - 提供建议和质量指标

标志

标志类型默认值描述
--typestringallunit、integration、e2e、all
--coverageboolfalse生成覆盖率报告
--watchboolfalse持续监视模式
--fixboolfalse自动修复简单的失败项
--gap-analysisboolfalse识别覆盖率缺口,但不生成测试
--generateboolfalse生成缺失的测试以达到目标
--targetint80覆盖率百分比目标
--modulestring-将范围限制在特定模块
--fix-firstboolfalse生成新测试前先修复现有失败项
--dry-runboolfalse显示缺口分析和测试计划,但不写入文件
--linkupboolfalse搜索网络以获取指导(通过 Rube MCP)
--querystring-LINKUP_SEARCH 的搜索查询

启用的角色

  • qa-specialist - 测试分析和质量评估

MCP 集成

PAL MCP(质量与调试)
工具使用时机用途
mcp__pal__debug测试失败时分析失败测试的根本原因
mcp__pal__codereview测试质量评估时审查测试覆盖率和质量
mcp__pal__thinkdeep复杂失败时多阶段调查不稳定的测试
mcp__pal__consensus制定测试策略时使用多个模型验证测试方法
mcp__pal__apilookup查阅框架文档时获取最新的测试框架文档
PAL 使用模式
# Debug failing test
mcp__pal__debug(
    step="Investigating intermittent test failure",
    hypothesis="Race condition in async setup",
    confidence="medium",
    relevant_files=["/tests/test_api.py"]
)

# Review test quality
mcp__pal__codereview(
    review_type="full",
    findings="Test coverage, assertion quality, edge cases",
    focus_on="test isolation and mocking patterns"
)

# Validate testing strategy
mcp__pal__consensus(
    models=[{"model": "gpt-5.2", "stance": "neutral"}, {"model": "gemini-3-pro", "stance": "neutral"}],
    step="Evaluate: Is integration testing sufficient for this feature?"
)
Rube MCP(自动化与研究)
工具使用时机用途
mcp__rube__RUBE_SEARCH_TOOLS集成 CI/CD 时查找测试报告工具
mcp__rube__RUBE_MULTI_EXECUTE_TOOL发送通知时将结果发布到 Slack、更新工单
mcp__rube__RUBE_REMOTE_WORKBENCH批量处理时分析大量测试结果集
Rube 使用模式
# Search for testing best practices (--linkup flag uses LINKUP_SEARCH)
mcp__rube__RUBE_MULTI_EXECUTE_TOOL(tools=[
    {"tool_slug": "LINKUP_SEARCH", "arguments": {
        "query": "pytest fixtures best practices",
        "depth": "deep",
        "output_type": "sourcedAnswer"
    }}
])

# Post test results to Slack
mcp__rube__RUBE_MULTI_EXECUTE_TOOL(tools=[
    {"tool_slug": "SLACK_SEND_MESSAGE", "arguments": {
        "channel": "#ci-results",
        "text": "Test run complete: 95% pass rate, 87% coverage"
    }}
])

证据要求

此技能要求提供证据。你必须:

  • 显示测试执行输出以及通过/失败数量
  • 使用 --coverage 时引用覆盖率指标
  • 提供实际的错误消息

测试类型定义

类型测试内容标记
单元测试隔离测试单个函数/类,并模拟其依赖项(无标记或使用框架默认标记)
集成测试多个组件协同工作,通过固定装置连接真实数据库@pytest.mark.integration、describe("integration")
端到端测试使用真实或模拟的外部 API 测试完整流程@pytest.mark.slow、@pytest.mark.e2e

阶段 1:覆盖率基线

1.1 运行当前覆盖率报告

检测测试框架并运行覆盖率检查:

# Python (pytest)
pytest --cov=src --cov-report=term-missing --cov-report=json:coverage.json -q --tb=no

# JavaScript (jest/vitest)
npx jest --coverage --coverageReporters=json-summary
# or: npx vitest run --coverage

# Go
go test -coverprofile=coverage.out ./...
go tool cover -func=coverage.out

# Rust
cargo tarpaulin --out json
1.2 解析覆盖率缺口

读取覆盖率报告并提取:

  • 每个文件的覆盖率百分比
  • 每个文件中未覆盖的行号
  • 项目总覆盖率

如果提供了 --module,则仅筛选指定模块的覆盖率数据。

1.3 生成缺口报告

按覆盖率缺口为文件排序(覆盖率最低的排在前面):

## Coverage Gap Report

**Current Coverage**: 52% | **Target**: 80% | **Gap**: 28%

| File | Coverage | Missing Lines | Priority |
|------|----------|---------------|----------|
| src/services/payment.py | 0% | 1-120 | CRITICAL |
| src/utils/validator.py | 15% | 12-45, 67-89 | HIGH |
| src/api/routes/users.py | 42% | 55-70, 88-102 | MEDIUM |

优先级规则:

  • CRITICAL:覆盖率为 0%(完全没有测试)
  • HIGH:覆盖率 < 30%
  • MEDIUM:覆盖率为 30-60%
  • LOW:覆盖率 > 60%,但低于目标值
1.4 与用户确认覆盖率优先级

生成缺口报告后,询问用户要优先处理哪些内容:

AskUserQuestion:
  question: "Found <N> files below target. Which should I tackle first?"
  header: "Priority"
  multiSelect: false
  options:
    - label: "Highest-impact first (Recommended)"
      description: "<N CRITICAL + M HIGH priority files -- start with 0% coverage modules>"
    - label: "Quick wins first"
      description: "Start with files that need only 1-2 tests to reach target"
    - label: "Specific module"
      description: "I want to focus on a specific area of the codebase"
    - label: "Dry run only"
      description: "Just show me the gap report -- don't write any tests yet"

如果选择“特定模块”:询问要重点处理哪个模块。 如果选择“仅试运行”:展示缺口报告并停止。

默认跳过以下文件:

  • 不含逻辑的协议/接口定义
  • 迁移文件
  • 仅包含重新导出的 __init__.py / index.ts
  • 生成的代码(protobuf、OpenAPI 客户端)

阶段 2:分析现有测试模式

编写任何测试之前,先了解项目的约定。

2.1 阅读测试基础设施

查找并阅读测试设置文件:

框架要阅读的文件
pytestconftest.py、pyproject.toml [tool.pytest]
jestjest.config.*、setupTests.*、__mocks__/
vitestvitest.config.*、setup.*
Go*_test.go 辅助文件、testdata/
Rusttests/common/mod.rs
2.2 查找模式示例

针对每个存在缺口的文件,找到最接近的现有测试作为模板:

  • 搜索相同目录/模块中的测试
  • 确认导入模式、固定装置用法和断言风格
  • 留意测试基类或共享辅助工具
2.3 确认可用的固定装置/辅助工具

将可用的测试固定装置对应到其使用场景。创建参考表:

| Fixture/Helper | Purpose | Used By |
|----------------|---------|---------|
| db_session | Database access | Integration tests |
| mock_api_client | Mock external API | Unit tests |
| ...            | ...     | ...     |
2.4 按测试类型分类函数
函数特征测试类型
纯函数(无 I/O、无数据库)单元测试
仅使用验证逻辑单元测试
调用数据库/ORM集成测试(需要数据库固定装置)
调用外部 API使用模拟对象的单元测试
HTTP 端点处理程序集成测试
完整流程执行端到端测试

阶段 3:按类型生成测试

按优先级处理缺口(先处理 CRITICAL)。对于每个文件:

3.1 阅读源模块

确认:

  • 所有公共函数和类
  • 它们的签名、返回类型和依赖项
  • 哪些依赖项需要模拟,哪些需要使用真实固定装置
  • 边界情况:空输入、None 值、错误条件
3.2 编写单元测试

遵循 AAA 模式(Arrange/Act/Assert,准备/执行/断言):

# Python example
class TestFunctionName:
    """Tests for function_name."""

    # Happy path
    async def test_returns_expected_result(self):
        """function_name returns correct output for valid input."""
        # Arrange
        input_data = ...

        # Act
        result = await function_under_test(input_data)

        # Assert
        assert result.field == expected_value

    # Edge cases
    async def test_handles_empty_input(self):
        """function_name handles empty input correctly."""
        ...

    # Error conditions (Let It Crash - verify errors propagate)
    async def test_raises_on_invalid_input(self):
        """function_name raises ValueError for invalid input."""
        with pytest.raises(ValueError):
            await function_under_test(invalid_input)
// TypeScript/Jest example
describe('functionName', () => {
  it('returns expected result for valid input', () => {
    // Arrange
    const input = { ... };

    // Act
    const result = functionName(input);

    // Assert
    expect(result.field).toBe(expectedValue);
  });

  it('throws on invalid input', () => {
    expect(() => functionName(invalidInput)).toThrow();
  });
});
// Go example
func TestFunctionName(t *testing.T) {
    t.Run("returns expected result", func(t *testing.T) {
        // Arrange
        input := ...

        // Act
        result, err := FunctionName(input)

        // Assert
        if err != nil {
            t.Fatalf("unexpected error: %v", err)
        }
        if result.Field != expected {
            t.Errorf("got %v, want %v", result.Field, expected)
        }
    })
}

适用于所有语言的规则:

  • 使用带注释的 AAA 模式(Arrange/Act/Assert,准备/执行/断言)
  • 文档字符串/描述应说明预期行为,而非实现方式
  • 仅模拟外部依赖项(API、数据库、网络)
  • 不要在测试中添加 try/except 或 try/catch(遵循 Let It Crash 原则)
  • 不要为了让测试通过而修改源代码(除非确实存在缺陷)
3.3 编写集成测试

对于需要数据库或多个组件的测试:

  • 使用适当的标记(@pytest.mark.integration、带标签的 describe 块)
  • 使用真实数据库固定装置或测试容器
  • 测试真实组件之间的交互,而非模拟对象之间的交互
  • 清理工作会通过固定装置的拆卸自动完成
3.4 编写端到端测试

对于完整流水线或 API 流程测试:

  • 使用 slow/e2e 标记
  • 使用 HTTP 测试客户端(httpx AsyncClient、supertest、net/http/httptest)
  • 通过夹具模拟外部 API 响应
  • 测试完整的请求/响应周期,包括身份验证
  • 验证响应架构是否与预期模型相符

第 4 阶段:验证测试

4.1 仅运行新测试
# Run just the newly created/modified test file
pytest tests/test_<area>/test_<module>.py -v --tb=short
npx jest tests/<module>.test.ts --verbose
go test -v -run TestNewFunction ./pkg/...
4.2 修复失败

如果测试失败:

  1. 仔细阅读错误输出
  2. 判断失败出在测试代码还是源代码
  3. 如果源代码的行为正确,则修复测试
  4. 绝不要为了让测试通过而修改源代码(除非确实存在 Bug)
  5. 如果源代码存在 Bug,请先询问用户是否要修复,而不是直接只测试当前行为
4.3 运行完整测试套件

所有新测试单独通过后:

# Full test suite - ensure no regressions
pytest -v --tb=short
npx jest --verbose
go test ./...
4.4 检查测试文件的代码规范
# Python
ruff check tests/ --fix && ruff format tests/

# TypeScript/JavaScript
npx eslint tests/ --fix && npx prettier tests/ --write

# Go
gofmt -w *_test.go

第 5 阶段:覆盖率验证

5.1 重新运行覆盖率检查

运行第 1 阶段中的相同覆盖率命令,以获取更新后的指标。

5.2 比较前后结果

报告覆盖率变化:

## Coverage Report

| Metric | Before | After | Delta |
|--------|--------|-------|-------|
| Total Coverage | 52% | 78% | +26% |
| Files with 0% | 5 | 1 | -4 |

### Per-File Improvements

| File | Before | After | Tests Added |
|------|--------|-------|-------------|
| src/services/payment.py | 0% | 85% | 8 |
| src/utils/validator.py | 15% | 72% | 5 |
5.3 询问是否继续迭代

如果覆盖率仍低于目标,请询问用户,而不是自动迭代:

AskUserQuestion:
  question: "Coverage is at <M%> (target: <N%>). Want to continue adding tests?"
  header: "Iterate"
  multiSelect: false
  options:
    - label: "Continue -- add more tests"
      description: "<K files remaining below target -- next batch would cover <list>"
    - label: "Good enough -- stop here"
      description: "Accept current coverage and move on"
    - label: "Raise the target"
      description: "Current coverage exceeded expectations -- set a higher target"
    - label: "Switch focus"
      description: "Cover a different area instead of continuing the current batch"

如果继续:

  1. 重新运行第 1 阶段,找出剩余缺口
  2. 优先处理未覆盖行数最多的文件
  3. 重复第 3 至第 5 阶段,直到达到目标或用户停止

最多迭代 5 次(遵循 --loop 约定)。


第 6 阶段:总结

呈现最终结果:

## Test Coverage Update Summary

**Target**: N%
**Achieved**: M%
**Tests Added**: X unit, Y integration, Z e2e

### New Test Files Created
- tests/test_<area>/test_<module>.py (N tests)
- ...

### Modified Test Files
- tests/test_<area>/test_<module>.py (+N tests)
- ...

### Coverage by Category
| Category | Coverage | Status |
|----------|----------|--------|
| src/services/ | ??% | OK/NEEDS WORK |
| src/routers/ | ??% | OK/NEEDS WORK |
| src/models/ | ??% | OK/NEEDS WORK |

### Remaining Gaps (if any)
- src/services/transformer.py - Excluded (needs full pipeline data)
- ...

### Verification Commands
<framework-specific commands to re-run tests and coverage>

应避免的反模式

不要编写以下测试:
  • 直接测试私有/内部方法(应通过公共 API 测试)
  • 重复已有的测试覆盖(先检查!)
  • 需要真实 API 密钥才能通过(模拟外部服务)
  • 依赖测试执行顺序
  • 使用 time.sleep() 进行异步同步
  • 捕获本应向上传播的异常(让它崩溃)
  • 添加防御性的 if x is not None 检查(测试约定)
不要:
  • 为了让代码“更易测试”而修改源代码(测试现有代码)
  • 在源文件中添加类型存根或文档字符串(只修改测试文件)
  • 创建测试工具框架或基类(保持简单)
  • 为少于 3 个用例编写参数化测试(直接分别编写测试)
  • 给你未修改的代码添加注释或文档字符串

覆盖率分析(独立运行)

仅启用 --coverage(不启用 --generate)时:

  • 行覆盖率指标
  • 分支覆盖率指标
  • 未覆盖代码识别
  • 覆盖率趋势比较

工具协调

  • Bash - 执行测试运行器
  • Glob - 查找测试文件
  • Grep - 解析结果、分析失败
  • Read - 检查源文件和测试文件
  • Write - 新建测试文件、生成覆盖率报告
  • Edit - 扩展现有测试文件
  • AskUserQuestion - 确认优先级、决定是否迭代

评论

支持 Markdown