golang-testing
Go测试模式包括表格驱动测试、子测试、基准测试、模糊测试和测试覆盖率。遵循TDD方法论,采用地道的Go实践。
DeepseekModel
Curated skill
Quality Excellent · 90
v1.0.0
Get
https://deepseekmodel.com/api/download.php?id=affaan-m-ecc-docs-zh-cn-skills-golang-testing-skill-md&format=skill
Download .skill
Standard format with system_prompt and model_config, ready for any agent framework
The actual content of the system_prompt field in the .skill file.
name golang-testing description Go测试模式包括表格驱动测试、子测试、基准测试、模糊测试和测试覆盖率。遵循TDD方法论,采用地道的Go实践。 origin ECC Go 测试模式 遵循 TDD 方法论,用于编写可靠、可维护测试的全面 Go 测试模式。 何时激活 编写新的 Go 函数或方法时 为现有代码添加测试覆盖率时 为性能关键代码创建基准测试时 为输入验证实现模糊测试时 在 Go 项目中遵循 TDD 工作流时 Go 的 TDD 工作流 红-绿-重构循环 RED → 首先编写一个失败的测试 GREEN → 编写最少的代码来通过测试 REFACTOR → 改进代码,同时保持测试通过 REPEAT → 继续处理下一个需求 Go 中的分步 TDD // Step 1: Define the interface/signature // calculator.go package calculator func Add (a, b int ) int { panic ( "not implemented" ) // Placeholder } // Step 2: Write failing test (RED) // calculator_test.go package calculator import "testing" func TestAdd (t *testing.T) { got := Add( 2 , 3 ) want := 5 if got != want { t.Errorf( "Add(2, 3) = %d; want %d" , got, want) } } // Step 3: Run test - verify FAIL // $ go test // --- FAIL: TestAdd (0.00s) // panic: not implemented // Step 4: Implement minimal code (GREEN) func Add (a, b int ) int { return a + b } // Step 5: Run test - verify PASS // $ go test // PASS // Step 6: Refactor if needed, verify tests still pass 表驱动测试 Go 测试的标准模式。以最少的代码实现全面的覆盖。 func TestAdd (t *testing.T) { tests := [] struct { name string a, b int expected int }{ { "positive numbers" , 2 , 3 , 5 }, { "negative numbers" , -1 , -2 , -3 }, { "zero values" , 0 , 0 , 0 }, { "mixed signs" , -1 , 1 , 0 }, { "large numbers" , 1000000 , 2000000 , 3000000 }, } for _, tt := range tests { t.Run(tt.name, func (t *testing.T) { got := Add(tt.a, tt.b) if got != tt.expected { t.Errorf( "Add(%d, %d) = %d; want %d" , tt.a, tt.b, got, tt.expected) } }) } } 包含错误情况的表驱动测试 func TestParseConfig (t *testing.T) { tests := [] struct { name string input string want *Config wantErr bool }{ { name: "valid config" , input: `{"host": "localhost", "port": 8080}` , want: &Config{Host: "localhost" , Port: 8080 }, }, { name: "invalid JSON" , input: `{invalid}` , wantErr: true , }, { name: "empty input" , input: "" , wantErr: true , }, { name: "minimal config" , input: `{}` , want: &Config{}, // Zero value config }, } for _, tt := range tests { t.Run(tt.name, func (t *testing.T) { got, err := ParseConfig(tt.input) if tt.wantErr { if err == nil { t.Error( "expected error, got nil" ) } return } if err != nil { t.Fatalf( "unexpected error: %v" , err) } if !reflect.DeepEqual(got, tt.want) { t.Errorf( "got %+v; want %+v" , got, tt.want) } }) } } 子测试和子基准测试 组织相关测试 func TestUser (t *testing.T) { // Setup shared by all subtests db := setupTestDB(t) t.Run( "Create" , func (t *testing.T) { user := &User{Name: "Alice" } err := db.CreateUser(user) if err != nil { t.Fatalf( "CreateUser failed: %v" , err) } if user.ID == "" { t.Error( "expected user ID to be set" ) } }) t.Run( "Get" , func (t *testing.T) { user, err := db.GetUser( "alice-id" ) if err != nil { t.Fatalf( "GetUser failed: %v" , err) } if user.Name != "Alice" { t.Errorf( "got name %q; want %q" , user.Name, "Alice" ) } }) t.Run( "Update" , func (t *testing.T) { // ... }) t.Run( "Delete" , func (t *testing.T) { // ... }) } 并行子测试 func TestParallel (t *testing.T) { tests := [] struct { name string input string }{ { "case1" , "input1" }, { "case2" , "input2" }, { "case3" , "input3" }, } for _, tt := range tests { tt := tt // Capture range variable t.Run(tt.name, func (t *testing.T) { t.Parallel() // Run subtests in parallel result := Process(tt.input) // assertions... _ = result }) } } 测试辅助函数 辅助函数 func setupTestDB (t *testing.T) *sql.DB { t.Helper() // Marks this as a helper function db, err := sql.Open( "sqlite3" , ":memory:" ) if err != nil { t.Fatalf( "failed to open database: %v" , err) } // Cleanup when test finishes t.Cleanup( func () { db.Close() }) // Run migrations if _, err := db.Exec(schema); err != nil { t.Fatalf( "failed to create schema: %v" , err) } return db } func assertNoError (t *testing.T, err error ) { t.Helper() if err != nil { t.Fatalf( "unexpected error: %v" , err) } } func assertEqual [ T comparable ] (t *testing.T, got, want T) { t.Helper() if got != want { t.Errorf( "got %v; want %v" , got, want) } } 临时文件和目录 func TestFileProcessing (t *testing.T) { // Create temp directory - automatically cleaned up tmpDir := t.TempDir() // Create test file testFile := filepath.Join(tmpDir, "test.txt" ) err := os.WriteFile(testFile, [] byte ( "test content" ), 0644 ) if err != nil { t.Fatalf( "failed to create test file: %v" , err) } // Run test result, err := ProcessFile(testFile) if err != nil { t.Fatalf( "ProcessFile failed: %v" , err) } // Assert... _ = result } 黄金文件 针对存储在 testdata/ 中的预期输出文件进行测试。 var update = flag.Bool( "update" , false , "update golden files" ) func TestRender (t *testing.T) { tests := [] struct { name string input Template }{ { "simple" , Template{Name: "test" }}, { "complex" , Template{Name: "test" , Items: [] string { "a" , "b" }}}, } for _, tt := range tests { t.Run(tt.name, func (t *testing.T) { got := Render(tt.input) golden := filepath.Join( "testdata" , tt.name+ ".golden" ) if *update { // Update golden file: go test -update err := os.WriteFile(golden, got, 0644 ) if err != nil { t.Fatalf( "failed to update golden file: %v" , err) } } want, err := os.ReadFile(golden) if err != nil { t.Fatalf( "failed to read golden file: %v" , err) } if !bytes.Equal(got, want) { t.Errorf( "output mismatch:\ngot:\n%s\nwant:\n%s" , got, want) } }) } } 使用接口进行模拟 基于接口的模拟 // Define interface for dependencies type UserRepository interface { GetUser(id string ) (*User, error ) SaveUser(user *User) error } // Production implementation type PostgresUserRepository struct { db *sql.DB } func (r *PostgresUserRepository) GetUser(id string ) (*User, error ) { // Real database query } // Mock implementation for tests type MockUserRepository struct { GetUserFunc func (id string ) (*User, error ) SaveUserFunc func (user *User) error } func (m *MockUserRepository) GetUser(id string ) (*User, error ) { return m.GetUserFunc(id) } func (m *MockUserRepository) SaveUser(user *User) error { return m.SaveUserFunc(user) } // Test using mock func TestUserService (t *testing.T) { mock := &MockUserRepository{ GetUserFunc: func (id string ) (*User, error ) { if id == "123" { return &User{ID: "123" , Name: "Alice" }, nil } return nil , ErrNotFound }, } service := NewUserService(mock) user, err := service.GetUserProfile( "123" ) if err != nil { t.Fatalf( "unexpected error: %v" , err) } if user.Name != "Alice" { t.Errorf( "got name %q; want %q" , user.Name, "Alice" ) } } 基准测试 基本基准测试 func BenchmarkProcess (b *testing.B) { data := generateTestData( 1000 ) b.ResetTimer() // Don't count setup time for i := 0 ; i < b.N; i++ { Process(data) } } // Run: go test -bench=BenchmarkProcess -benchmem // Output: BenchmarkProcess-8 10000 105234 ns/op 4096 B/op 10 allocs/op 不同大小的基准测试 func BenchmarkSort (b *testing.B) { sizes := [] int { 100 , 1000 , 10000 , 100000 } for _, size := range sizes { b.Run(fmt.Sprintf( "size=%d" , size), func (b *testing.B) { data := generateRandomSlice(size) b.ResetTimer() for i := 0 ; i < b.N; i++ { // Make a copy to avoid sorting already sorted data tmp := make ([] int , len (data)) copy (tmp, data) sort.Ints(tmp) } }) } } 内存分配基准测试 func BenchmarkStringConcat (b *testing.B) { parts := [] string { "hello" , "world" , "foo" , "bar" , "baz" } b.Run( "plus" , func (b *testing.B) { for i := 0 ; i < b.N; i++ { var s string for _, p := range parts { s += p } _ = s } }) b.Run( "builder" , func (b *testing.B) { for i := 0 ; i < b.N; i++ { var sb strings.Builder for _, p := range parts { sb.WriteString(p) } _ = sb.String() } }) b.Run( "join" , func (b *testing.B) { for i := 0 ; i < b.N; i++ { _ = strings.Join(parts, "" ) } }) } 模糊测试 (Go 1.18+) 基本模糊测试 func FuzzParseJSON (f *testing.F) { // Add seed corpus f.Add( `{"name": "test"}` ) f.Add( `{"count": 123}` )
Keywords that activate this skill. Click one to copy it.
This skill does not provide trigger words.
The downloaded .skill package contains the following fields.
| Field | Description |
|---|---|
| format | Format tag (skill/v1) |
| skill_id | Unique skill ID |
| name | Skill name |
| version | Version |
| description | Description |
| category | Categories (array) |
| trigger_words | Trigger words |
| tags | Tags |
| source | Source |
| source_url | Source URL (this page) |
| exported_at | Exported at (set per download) |
| system_prompt | System prompt body |
| model_config | Model config: provider / model / temperature / max_tokens / top_p |
| examples | Examples |
| install_guide | Import guide for Coze / Dify / Claude / custom frameworks |
The same skill can be exported in different platform formats.