Loading...
Loading...
Compare original and translation side by side
t.Runt.Helper()go testgo test -racepackage_testpackageTestConsumeLoop_CanBeReenteredAfterFailureTestRestartLoop_RestartsAfterTransientFailureconsumeLoopStart()t.Runt.Helper()go testgo test -racepackage_testpackageconsumeLoopStart()TestConsumeLoop_CanBeReenteredAfterFailureTestRestartLoop_RestartsAfterTransientFailuret.Parallel()t.Cleanup()t.Context()b.Loop()for i := 0; i < b.N; i++go_diagnostics-coverprofilet.Parallel()t.Cleanup()t.Context()b.Loop()for i := 0; i < b.N; i++go_diagnostics-coverprofiletesting/synctestbenchstattesting/synctestbenchstatscripts/gen-table-test.shbash scripts/gen-table-test.sh --helpscripts/bench-compare.shbash scripts/bench-compare.sh --helpscripts/gen-table-test.shbash scripts/gen-table-test.sh --helpscripts/bench-compare.shbash scripts/bench-compare.sh --helpt.Runt.Helper()b.Loop()t.Runt.Helper()b.Loop()systematic-debuggingtest-driven-developmentgolang-general-engineersystematic-debuggingtest-driven-developmentgolang-general-engineer| 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 | |
package mypackage_test // Black-box testing (preferred)
import (
"testing"
"mymodule/mypackage"
)
// Order: Unit tests, Integration tests, Benchmarks, Examples| 需求 | 测试类型 | 实现模式 |
|---|---|---|
| 多组输入/输出用例 | 表驱动单元测试 | |
| 单一特定行为 | 聚焦型单元测试 | 标准 |
| 跨组件交互 | 集成测试 | 初始化/清理辅助函数 |
| 性能度量 | 基准测试 | |
| API使用文档 | 示例测试 | |
package mypackage_test // 黑盒测试(优先选择)
import (
"testing"
"mymodule/mypackage"
)
// 顺序:单元测试、集成测试、基准测试、示例测试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)
}
})
}
}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)
}
}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
}references/go-test-patterns.mdfor _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
// test body (use tt directly in Go 1.22+)
})
}t.Helper()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)
}
})
}
}func assertEqual[T comparable](t *testing.T, got, want T) {
t.Helper() // 必须是第一行
if got != want {
t.Errorf("got %v, want %v", got, want)
}
}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
}references/go-test-patterns.mdfor _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
// 测试体(Go 1.22+可直接使用tt变量)
})
}t.Helper()undefinedundefined
**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 ./...
**步骤2:验证结果**
- 所有测试通过(显示实际输出)
- 未检测到竞态条件
- 关键路径覆盖率>80%
- 错误路径已覆盖
**步骤3:运行全量测试套件**
```bash
go test ./...t.Helper()t.Cleanupdefert.Helper()t.Cleanupdeferb.Loop()func BenchmarkProcess(b *testing.B) {
b.ReportAllocs()
for b.Loop() {
_ = Process(input)
}
}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 ./...references/go-benchmark-and-concurrency.mdb.Loop()func BenchmarkProcess(b *testing.B) {
b.ReportAllocs()
for b.Loop() {
_ = Process(input)
}
}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 ./...references/go-benchmark-and-concurrency.mdgo 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 testsgo 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 ./... # 检测不稳定测试sync.Mutexatomicreferences/go-benchmark-and-concurrency.mdsync.Mutexatomicreferences/go-benchmark-and-concurrency.mdt.TempDir()t.Setenv()time.Sleepsynctest.Testt.TempDir()t.Setenv()synctest.Testtime.SleepTestParseValidTestParseInvalidTestParseEmptyTestParset.RunTestParseValidTestParseInvalidTestParseEmptyTestParset.Runt.Helper()t.Helper()t.Cleanup()t.Cleanup()os.ReadFile("testdata/input.json")t.TempDir()os.Getwd()os.ReadFile("testdata/input.json")t.TempDir()os.Getwd()| 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并跟踪调用 |
${CLAUDE_SKILL_DIR}/references/go-test-patterns.md${CLAUDE_SKILL_DIR}/references/go-benchmark-and-concurrency.md${CLAUDE_SKILL_DIR}/references/go-test-patterns.md${CLAUDE_SKILL_DIR}/references/go-benchmark-and-concurrency.md