关于 sc-test
sc-test 是用于测试执行与覆盖率改进的技能,面向需要分析测试缺口并逐步补充测试的开发工作。它结合覆盖率报告、交互式优先级确认、按项目约定生成测试和复查结果。
主要功能
- 01运行不同类型的测试
- 02生成覆盖率报告
- 03定位并排序覆盖缺口
- 04按项目模式生成测试
- 05复跑测试并比较覆盖率
适用场景
- 01查找覆盖率不足的文件
- 02按优先级补充单元或集成测试
- 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。 测试覆盖率需要在速度与全面性之间权衡。请确认优先级,而不是猜测用户希望覆盖哪些内容。
- 编写测试之前——确认优先处理哪些模块
- 缺口较大时——询问应优先将精力放在哪里
- 源代码看起来有缺陷时——在修复还是仅测试之间做出选择前先询问
- 覆盖率运行结束后——询问是继续迭代还是停止
行为流程
- 发现 - 使用运行器模式对测试进行分类
- 配置 - 设置测试环境和参数
- 执行 - 运行测试并实时跟踪进度
- 分析 - 生成覆盖率报告和诊断信息
- 确认优先级 - 交互式检查点:询问用户要处理哪些内容
- 研究模式 - 阅读测试基础设施和现有惯例
- 生成 - 按照项目惯例编写缺失的测试
- 验证 - 运行新测试、修复失败项并执行 lint
- 核实覆盖率 - 重新运行覆盖率并比较前后结果
- 迭代 - 询问用户:继续、停止或更改重点
- 报告 - 提供建议和质量指标
标志
| 标志 | 类型 | 默认值 | 描述 |
|---|---|---|---|
--type | string | all | unit、integration、e2e、all |
--coverage | bool | false | 生成覆盖率报告 |
--watch | bool | false | 持续监视模式 |
--fix | bool | false | 自动修复简单的失败项 |
--gap-analysis | bool | false | 识别覆盖率缺口,但不生成测试 |
--generate | bool | false | 生成缺失的测试以达到目标 |
--target | int | 80 | 覆盖率百分比目标 |
--module | string | - | 将范围限制在特定模块 |
--fix-first | bool | false | 生成新测试前先修复现有失败项 |
--dry-run | bool | false | 显示缺口分析和测试计划,但不写入文件 |
--linkup | bool | false | 搜索网络以获取指导(通过 Rube MCP) |
--query | string | - | 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 阅读测试基础设施
查找并阅读测试设置文件:
| 框架 | 要阅读的文件 |
|---|---|
| pytest | conftest.py、pyproject.toml [tool.pytest] |
| jest | jest.config.*、setupTests.*、__mocks__/ |
| vitest | vitest.config.*、setup.* |
| Go | *_test.go 辅助文件、testdata/ |
| Rust | tests/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 修复失败
如果测试失败:
- 仔细阅读错误输出
- 判断失败出在测试代码还是源代码
- 如果源代码的行为正确,则修复测试
- 绝不要为了让测试通过而修改源代码(除非确实存在 Bug)
- 如果源代码存在 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 阶段,找出剩余缺口
- 优先处理未覆盖行数最多的文件
- 重复第 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 - 确认优先级、决定是否迭代