go-testing
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseGo Testing Skill
Go语言测试技能指南
Operator Context
操作场景
This skill operates as an operator for Go testing workflows, configuring Claude's behavior for idiomatic, thorough Go test development. It implements the Pattern Library architectural pattern -- applying canonical Go testing patterns (table-driven, subtests, helpers, mocking) with Domain Intelligence from the Go standard library's testing conventions.
本技能作为Go语言测试工作流的操作指引,用于配置Claude的行为,以实现符合Go语言惯用风格且全面的测试开发。它采用模式库架构模式——结合Go标准库测试约定中的领域智能,应用经典的Go测试模式(表驱动、子测试、辅助函数、Mock)。
Hardcoded Behaviors (Always Apply)
硬性规则(必须始终遵守)
- CLAUDE.md Compliance: Read and follow repository CLAUDE.md before writing tests
- Over-Engineering Prevention: Write only the tests needed. No speculative coverage, no "while I'm here" test additions
- Table-Driven Tests Required: Multiple related cases MUST use table-driven pattern with
t.Run - t.Helper() Required: Every test helper function MUST call as its first line
t.Helper() - Show Test Output: Always show actual output. Never summarize as "tests pass"
go test - Race Detector: Run when testing concurrent code
go test -race - Black-Box Testing: Prefer (external test package) over
package_test(internal)package - Test Name Accuracy: Test names must accurately describe the code path exercised. If a test simulates behavior rather than exercising the production code path, the name must reflect this (e.g., not
TestConsumeLoop_CanBeReenteredAfterFailurewhen the test callsTestRestartLoop_RestartsAfterTransientFailuredirectly instead ofconsumeLoop). "Pragmatic approximation" is not a valid reason for a misleading test name.Start()
- 遵循CLAUDE.md规范:编写测试前请阅读并遵循仓库中的CLAUDE.md
- 避免过度设计:仅编写必要的测试,不做投机性覆盖,不添加“顺手而为”的测试用例
- 必须使用表驱动测试:多个相关测试用例必须使用表驱动模式结合实现
t.Run - 必须调用t.Helper():每个测试辅助函数必须将作为第一行代码
t.Helper() - 展示测试输出:始终显示的实际输出,绝不简单总结为“测试通过”
go test - 竞态检测器:测试并发代码时必须运行
go test -race - 黑盒测试优先:优先使用(外部测试包)而非
package_test(内部包)package - 测试名称准确:测试名称必须准确描述所执行的代码路径。如果测试模拟行为而非执行生产代码路径,名称必须反映这一点(例如,当测试直接调用而非
consumeLoop时,应命名为Start(),而非TestConsumeLoop_CanBeReenteredAfterFailure)。“务实近似”不能成为测试名称误导的理由。TestRestartLoop_RestartsAfterTransientFailure
Default Behaviors (ON unless disabled)
默认行为(除非禁用否则启用)
- Parallel Execution: Use for independent tests by default
t.Parallel() - t.Cleanup Over defer: Prefer for resource management in test helpers
t.Cleanup() - t.Context(): Use (Go 1.24+) for context-aware tests
t.Context() - b.Loop(): Use (Go 1.24+) instead of
b.Loop()for benchmarksfor i := 0; i < b.N; i++ - gopls Diagnostics: After editing test files, use to catch errors before running tests
go_diagnostics - Error Path Testing: Test error conditions, not just happy paths
- Coverage Check: Run and verify critical paths have >80% coverage
-coverprofile - Cleanup Verification: Each test must clean up after itself (no test pollution)
- 并行执行:默认对独立测试使用
t.Parallel() - 优先使用t.Cleanup而非defer:在测试辅助函数中优先使用进行资源管理
t.Cleanup() - 使用t.Context():在Go 1.24+版本中使用实现上下文感知测试
t.Context() - 使用b.Loop():在Go 1.24+版本中,基准测试使用替代
b.Loop()for i := 0; i < b.N; i++ - gopls诊断:编辑测试文件后,使用在运行测试前捕获错误
go_diagnostics - 错误路径测试:测试错误场景,而非仅测试正常路径
- 覆盖率检查:运行并验证关键路径覆盖率>80%
-coverprofile - 清理验证:每个测试必须自行清理资源(避免测试污染)
Optional Behaviors (OFF unless enabled)
可选行为(除非启用否则禁用)
- synctest Usage: Use (Go 1.25+) for deterministic concurrency testing
testing/synctest - Benchmark Comparison: Use for before/after performance comparisons
benchstat - Coverage HTML Report: Generate and open HTML coverage visualization
- Interface Deduplication: Test multiple interface implementations with shared test functions
- 使用synctest:在Go 1.25+版本中使用进行确定性并发测试
testing/synctest - 基准测试对比:使用进行基准测试前后的性能对比
benchstat - 生成覆盖率HTML报告:生成并打开可视化的覆盖率HTML报告
- 接口去重测试:使用共享测试函数测试多个接口实现
Available Scripts
可用脚本
- — Scaffold a table-driven test file for a Go function. Run
scripts/gen-table-test.shfor options.bash scripts/gen-table-test.sh --help - — Run Go benchmarks with optional benchstat comparison. Run
scripts/bench-compare.shfor options.bash scripts/bench-compare.sh --help
- — 为Go函数快速生成表驱动测试文件。运行
scripts/gen-table-test.sh查看选项。bash scripts/gen-table-test.sh --help - — 运行Go基准测试并可选使用benchstat进行对比。运行
scripts/bench-compare.sh查看选项。bash scripts/bench-compare.sh --help
What This Skill CAN Do
本技能可实现的功能
- Write idiomatic table-driven tests with subtests
t.Run - Create test helpers with proper marking
t.Helper() - Build manual mock implementations for interfaces
- Write benchmarks using modern pattern
b.Loop() - Set up parallel tests with proper variable capture
- Guide race detection and concurrent test patterns
- 编写符合Go惯用风格的表驱动测试(结合子测试)
t.Run - 创建正确标记的测试辅助函数
t.Helper() - 为接口构建手动Mock实现
- 使用现代模式编写基准测试
b.Loop() - 正确设置并行测试并处理变量捕获
- 指导竞态检测与并发测试模式
What This Skill CANNOT Do
本技能不可实现的功能
- Debug failing tests (use instead)
systematic-debugging - Write non-Go tests (use instead)
test-driven-development - Perform general Go development (use directly)
golang-general-engineer - Generate code from mocking frameworks (manual mocks preferred in Go)
- Optimize performance without test focus (use performance profiling tools)
- 调试测试失败问题(请改用)
systematic-debugging - 编写非Go语言测试(请改用)
test-driven-development - 通用Go开发(请直接使用)
golang-general-engineer - 使用Mock框架生成代码(Go语言中优先使用手动Mock)
- 无测试重点的性能优化(请使用性能分析工具)
Instructions
操作步骤
Phase 1: UNDERSTAND Test Requirements
阶段1:理解测试需求
Goal: Determine what needs testing and the appropriate test strategy.
Step 1: Identify test scope
- What function/method/package is being tested?
- Is this a new test, modification, or coverage gap?
- Are there existing tests to follow as patterns?
Step 2: Choose test type
| Need | Test Type | Pattern |
|---|---|---|
| Multiple input/output cases | Table-driven unit test | |
| Single specific behavior | Focused unit test | Standard |
| Cross-component interaction | Integration test | Setup/teardown helpers |
| Performance measurement | Benchmark | |
| API usage documentation | Example test | |
Step 3: Verify test file structure
go
package mypackage_test // Black-box testing (preferred)
import (
"testing"
"mymodule/mypackage"
)
// Order: Unit tests, Integration tests, Benchmarks, ExamplesGate: Test scope, type, and file location identified. Proceed only when gate passes.
目标:确定需要测试的内容及合适的测试策略。
步骤1:明确测试范围
- 要测试的函数/方法/包是什么?
- 这是新测试、测试修改还是覆盖率补充?
- 是否有可参考的现有测试模式?
步骤2:选择测试类型
| 需求 | 测试类型 | 实现模式 |
|---|---|---|
| 多组输入/输出用例 | 表驱动单元测试 | |
| 单一特定行为 | 聚焦型单元测试 | 标准 |
| 跨组件交互 | 集成测试 | 初始化/清理辅助函数 |
| 性能度量 | 基准测试 | |
| API使用文档 | 示例测试 | |
步骤3:验证测试文件结构
go
package mypackage_test // 黑盒测试(优先选择)
import (
"testing"
"mymodule/mypackage"
)
// 顺序:单元测试、集成测试、基准测试、示例测试准入条件:已明确测试范围、类型及文件位置。仅当满足条件时方可进入下一阶段。
Phase 2: WRITE Tests
阶段2:编写测试
Goal: Implement tests following Go idioms.
Step 1: Table-driven tests for multiple cases
Every function with more than one test case MUST use table-driven pattern:
go
func TestParseConfig(t *testing.T) {
tests := []struct {
name string
input string
want Config
wantErr bool
}{
{
name: "valid YAML",
input: `key: value`,
want: Config{Key: "value"},
},
{
name: "invalid syntax",
input: `{{{`,
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := ParseConfig(tt.input)
if (err != nil) != tt.wantErr {
t.Errorf("ParseConfig() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !tt.wantErr && got != tt.want {
t.Errorf("ParseConfig() = %v, want %v", got, tt.want)
}
})
}
}Step 2: Test helpers with t.Helper()
go
func assertEqual[T comparable](t *testing.T, got, want T) {
t.Helper() // MUST be first line
if got != want {
t.Errorf("got %v, want %v", got, want)
}
}Step 3: Mocking interfaces
Use manual mocks with function fields for flexible per-test behavior:
go
type MockStore struct {
GetFunc func(key string) ([]byte, error)
}
func (m *MockStore) Get(key string) ([]byte, error) {
if m.GetFunc != nil {
return m.GetFunc(key)
}
return nil, nil
}See for complete mock patterns with call tracking.
references/go-test-patterns.mdStep 4: Parallel tests
go
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
// test body (use tt directly in Go 1.22+)
})
}Gate: Tests follow table-driven pattern, helpers use , mocks use function fields. Proceed only when gate passes.
t.Helper()目标:遵循Go语言惯用风格实现测试。
步骤1:多场景表驱动测试
所有包含多个测试用例的函数必须使用表驱动模式:
go
func TestParseConfig(t *testing.T) {
tests := []struct {
name string
input string
want Config
wantErr bool
}{
{
name: "valid YAML",
input: `key: value`,
want: Config{Key: "value"},
},
{
name: "invalid syntax",
input: `{{{`,
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := ParseConfig(tt.input)
if (err != nil) != tt.wantErr {
t.Errorf("ParseConfig() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !tt.wantErr && got != tt.want {
t.Errorf("ParseConfig() = %v, want %v", got, tt.want)
}
})
}
}步骤2:带t.Helper()的测试辅助函数
go
func assertEqual[T comparable](t *testing.T, got, want T) {
t.Helper() // 必须是第一行
if got != want {
t.Errorf("got %v, want %v", got, want)
}
}步骤3:接口Mock
使用带函数字段的手动Mock实现灵活的单测行为:
go
type MockStore struct {
GetFunc func(key string) ([]byte, error)
}
func (m *MockStore) Get(key string) ([]byte, error) {
if m.GetFunc != nil {
return m.GetFunc(key)
}
return nil, nil
}完整的Mock模式(含调用跟踪)请参考。
references/go-test-patterns.md步骤4:并行测试
go
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
// 测试体(Go 1.22+可直接使用tt变量)
})
}准入条件:测试遵循表驱动模式、辅助函数使用、Mock使用函数字段。仅当满足条件时方可进入下一阶段。
t.Helper()Phase 3: RUN and Verify
阶段3:运行并验证
Goal: Execute tests and confirm correctness.
Step 1: Run tests
bash
undefined目标:执行测试并确认正确性。
步骤1:运行测试
bash
undefinedStandard run with verbose output
标准运行并显示详细输出
go test -v ./path/to/package/...
go test -v ./path/to/package/...
With race detector (REQUIRED for concurrent code)
启用竞态检测器(并发代码必须执行)
go test -race -v ./path/to/package/...
go test -race -v ./path/to/package/...
With coverage
生成覆盖率报告
go test -coverprofile=coverage.out ./path/to/package/...
go tool cover -func=coverage.out
**Step 2: Verify results**
- All tests pass (show actual output)
- No race conditions detected
- Critical paths have >80% coverage
- Error paths are exercised
**Step 3: Run full suite**
```bash
go test ./...Verify no regressions in other packages.
Gate: All tests pass, race detector clean, coverage adequate. Proceed only when gate passes.
go test -coverprofile=coverage.out ./path/to/package/...
go tool cover -func=coverage.out
**步骤2:验证结果**
- 所有测试通过(显示实际输出)
- 未检测到竞态条件
- 关键路径覆盖率>80%
- 错误路径已覆盖
**步骤3:运行全量测试套件**
```bash
go test ./...验证其他包无回归问题。
准入条件:所有测试通过、竞态检测无问题、覆盖率达标。仅当满足条件时方可进入下一阶段。
Phase 4: REVIEW Test Quality
阶段4:评审测试质量
Goal: Ensure tests are maintainable and complete.
Checklist:
- Table-driven tests for multiple cases?
- Test helpers marked with ?
t.Helper() - Parallel execution where safe?
- Error conditions tested?
- Edge cases covered (empty, nil, boundary)?
- Cleanup performed (or
t.Cleanup)?defer - No test interdependencies?
- Race detector passes?
Gate: All checklist items satisfied. Tests are complete.
目标:确保测试可维护且完整。
检查清单:
- 多场景使用表驱动测试?
- 测试辅助函数标记?
t.Helper() - 安全场景下启用并行执行?
- 测试错误条件?
- 覆盖边缘场景(空值、nil、边界值)?
- 执行资源清理(或
t.Cleanup)?defer - 测试无依赖关系?
- 竞态检测通过?
准入条件:所有检查项均满足。测试完成。
Benchmark Guide
基准测试指南
Use (Go 1.24+) for all new benchmarks. It prevents dead code elimination, manages timers automatically, and produces more accurate results.
b.Loop()go
func BenchmarkProcess(b *testing.B) {
b.ReportAllocs()
for b.Loop() {
_ = Process(input)
}
}Sub-benchmarks for comparison:
go
func BenchmarkBuilder(b *testing.B) {
b.Run("strings.Builder", func(b *testing.B) {
b.ReportAllocs()
for b.Loop() { /* ... */ }
})
b.Run("bytes.Buffer", func(b *testing.B) {
b.ReportAllocs()
for b.Loop() { /* ... */ }
})
}Run:
go test -bench=. -benchmem ./...See for benchstat comparison workflow and synctest patterns.
references/go-benchmark-and-concurrency.md所有新基准测试必须使用(Go 1.24+)。它可防止死代码消除、自动管理计时器,并产生更准确的结果。
b.Loop()go
func BenchmarkProcess(b *testing.B) {
b.ReportAllocs()
for b.Loop() {
_ = Process(input)
}
}用于对比的子基准测试:
go
func BenchmarkBuilder(b *testing.B) {
b.Run("strings.Builder", func(b *testing.B) {
b.ReportAllocs()
for b.Loop() { /* ... */ }
})
b.Run("bytes.Buffer", func(b *testing.B) {
b.ReportAllocs()
for b.Loop() { /* ... */ }
})
}运行命令:
go test -bench=. -benchmem ./...benchstat对比流程及synctest模式请参考。
references/go-benchmark-and-concurrency.mdCommands Reference
命令参考
bash
go test ./... # Run all tests
go test -v ./... # Verbose output
go test -race ./... # Race detector
go test -run TestMyFunc ./... # Specific test
go test -run TestMyFunc/subtest ./... # Specific subtest
go test -coverprofile=coverage.out ./... # Coverage profile
go tool cover -func=coverage.out # Coverage summary
go tool cover -html=coverage.out # Coverage HTML
go test -bench=. -benchmem ./... # Benchmarks
go test -short ./... # Skip long tests
go test -timeout 30s ./... # With timeout
go test -count=10 ./... # Detect flaky testsbash
go test ./... # 运行所有测试
go test -v ./... # 显示详细输出
go test -race ./... # 启用竞态检测器
go test -run TestMyFunc ./... # 运行指定测试
go test -run TestMyFunc/subtest ./... # 运行指定子测试
go test -coverprofile=coverage.out ./... # 生成覆盖率文件
go tool cover -func=coverage.out # 查看覆盖率摘要
go tool cover -html=coverage.out # 生成HTML覆盖率报告
go test -bench=. -benchmem ./... # 运行基准测试
go test -short ./... # 跳过耗时测试
go test -timeout 30s ./... # 设置超时时间
go test -count=10 ./... # 检测不稳定测试Error Handling
错误处理
Error: "test passes but shouldn't"
错误:“测试本应失败却通过了”
Cause: Test assertion is wrong or testing the wrong thing (tautological test)
Solution:
- Verify test actually exercises the code under test
- Temporarily break the implementation and confirm test fails
- Check assertion compares meaningful values, not self-referential ones
原因:测试断言错误或测试对象错误(同义反复测试)
解决方案:
- 验证测试是否真正执行了被测代码
- 临时破坏实现逻辑,确认测试会失败
- 检查断言是否有意义,而非自引用比较
Error: "race detected during test"
错误:“测试中检测到竞态条件”
Cause: Shared mutable state accessed from goroutines without synchronization
Solution:
- Use or
sync.Mutexoperations for shared stateatomic - Use channels for goroutine communication
- Ensure mock call tracking uses mutex protection
- See for patterns
references/go-benchmark-and-concurrency.md
原因:goroutine访问共享可变状态时未同步
解决方案:
- 对共享状态使用或
sync.Mutex操作atomic - 使用channel进行goroutine通信
- 确保Mock调用跟踪使用互斥锁保护
- 参考中的模式
references/go-benchmark-and-concurrency.md
Error: "test passes locally but fails in CI"
错误:“本地测试通过但CI中失败”
Cause: Environment dependency, timing assumption, or file path difference
Solution:
- Use instead of hardcoded paths
t.TempDir() - Use for environment variables (auto-restored)
t.Setenv() - Replace with
time.Sleepfor timing-dependent testssynctest.Test - Check for platform-specific assumptions
原因:环境依赖、时间假设或文件路径差异
解决方案:
- 使用替代硬编码路径
t.TempDir() - 使用设置环境变量(自动恢复)
t.Setenv() - 用替代
synctest.Test处理依赖时间的测试time.Sleep - 检查平台相关假设
Anti-Patterns
反模式
Anti-Pattern 1: Separate Functions for Related Cases
反模式1:相关场景使用独立函数
What it looks like: , , as separate functions
Why wrong: Duplicates setup, obscures the input-output relationship, harder to add cases
Do instead: One with table-driven cases and subtests
TestParseValidTestParseInvalidTestParseEmptyTestParset.Run表现:将、、作为独立函数
问题:重复初始化代码、模糊输入输出关系、新增场景更困难
正确做法:使用一个函数结合表驱动场景和子测试
TestParseValidTestParseInvalidTestParseEmptyTestParset.RunAnti-Pattern 2: Missing t.Helper()
反模式2:遗漏t.Helper()
What it looks like: Test helper reports errors at the helper's line, not the caller's
Why wrong: Makes debugging test failures slow because error location is misleading
Do instead: Add as the first line of every test helper function
t.Helper()表现:测试辅助函数报错时指向辅助函数行,而非调用者行
问题:错误位置误导,增加调试时间
正确做法:每个测试辅助函数第一行必须添加
t.Helper()Anti-Pattern 3: Testing Implementation Instead of Behavior
反模式3:测试实现细节而非行为
What it looks like: Asserting internal method calls, field values, or execution order
Why wrong: Breaks on every refactor even when behavior is unchanged
Do instead: Test observable behavior (return values, side effects, state changes)
表现:断言内部方法调用、字段值或执行顺序
问题:重构代码时即使行为未变,测试也会失败
正确做法:测试可观察行为(返回值、副作用、状态变化)
Anti-Pattern 4: Test Pollution via Shared State
反模式4:共享状态导致测试污染
What it looks like: Package-level variables modified by tests, test order matters
Why wrong: Tests become flaky, pass individually but fail together
Do instead: Create fresh state in each test. Use for teardown.
t.Cleanup()表现:测试修改包级变量,测试执行顺序影响结果
问题:测试变得不稳定,单独运行通过但批量运行失败
正确做法:每个测试创建独立状态,使用进行清理
t.Cleanup()Anti-Pattern 5: Hardcoded File Paths
反模式5:硬编码文件路径
What it looks like: without considering working directory
Why wrong: Breaks when test runs from different directory or in CI
Do instead: Use for generated files, + relative path for testdata
os.ReadFile("testdata/input.json")t.TempDir()os.Getwd()表现:使用未考虑工作目录
问题:在不同目录或CI环境中运行时失败
正确做法:使用存储生成文件,使用+相对路径访问testdata
os.ReadFile("testdata/input.json")t.TempDir()os.Getwd()References
参考资料
This skill uses these shared patterns:
- Anti-Rationalization Core - Prevents shortcut rationalizations
- Anti-Rationalization Testing - Testing-specific rationalization prevention
- Verification Checklist - Pre-completion checks
本技能使用以下共享模式:
- Anti-Rationalization Core - 避免捷径合理化
- Anti-Rationalization Testing - 测试场景下的合理化避免
- Verification Checklist - 完成前检查
Domain-Specific Anti-Rationalization
领域特定反合理化
| Rationalization | Why It's Wrong | Required Action |
|---|---|---|
| "One test case, no need for table-driven" | Will grow to multiple cases | Set up table-driven from the start |
| "t.Helper() is just cosmetic" | Wrong error location wastes debug time | Always add t.Helper() |
| "Tests pass, no need for -race" | Race conditions are silent until production | Run with -race for concurrent code |
| "Coverage is 80%, good enough" | What's in the uncovered 20%? | Check that critical paths are covered |
| "Mock is too complex to build" | Complex ≠ optional | Build the mock, track calls |
| 合理化借口 | 问题所在 | 要求动作 |
|---|---|---|
| “只有一个测试用例,不需要表驱动” | 后续会新增多个场景 | 从一开始就使用表驱动模式 |
| “t.Helper()只是 cosmetic” | 错误位置浪费调试时间 | 必须添加t.Helper() |
| “测试通过了,不需要-race” | 竞态条件在生产环境才会显现 | 并发代码必须运行-race |
| “覆盖率80%,足够了” | 未覆盖的20%是什么? | 检查关键路径是否覆盖 |
| “Mock太复杂,没必要做” | 复杂≠可选 | 构建Mock并跟踪调用 |
Reference Files
参考文件
- : Full examples for table-driven tests, helpers, mocking, interface deduplication
${CLAUDE_SKILL_DIR}/references/go-test-patterns.md - : b.Loop() benchmarks, benchstat, synctest, race detection patterns
${CLAUDE_SKILL_DIR}/references/go-benchmark-and-concurrency.md
- :表驱动测试、辅助函数、Mock、接口去重的完整示例
${CLAUDE_SKILL_DIR}/references/go-test-patterns.md - :b.Loop()基准测试、benchstat、synctest、竞态检测模式
${CLAUDE_SKILL_DIR}/references/go-benchmark-and-concurrency.md