golang-testing
Go testing patterns including table-driven tests, subtests, benchmarks, fuzzing, and test coverage. Follows TDD methodology with idiomatic Go practices. Use when writing Go tests — table-driven cases, subtests, benchmarks, fuzzing, or coverage.
DeepseekModel
Curated skill
Quality Excellent · 90
v1.0.0
Get
https://deepseekmodel.com/api/download.php?id=affaan-m-ecc-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 testing patterns including table-driven tests, subtests, benchmarks, fuzzing, and test coverage. Follows TDD methodology with idiomatic Go practices. Use when writing Go tests — table-driven cases, subtests, benchmarks, fuzzing, or coverage. metadata {"origin":"ECC"} Go Testing Patterns Comprehensive Go testing patterns for writing reliable, maintainable tests following TDD methodology. When to Activate Writing new Go functions or methods Adding test coverage to existing code Creating benchmarks for performance-critical code Implementing fuzz tests for input validation Following TDD workflow in Go projects TDD Workflow for Go The RED-GREEN-REFACTOR Cycle RED → Write a failing test first GREEN → Write minimal code to pass the test REFACTOR → Improve code while keeping tests green REPEAT → Continue with next requirement Step-by-Step TDD in Go // 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 Table-Driven Tests The standard pattern for Go tests. Enables comprehensive coverage with minimal code. 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) } }) } } Table-Driven Tests with Error Cases 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) } }) } } Subtests and Sub-benchmarks Organizing Related Tests 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) { // ... }) } Parallel Subtests 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 }) } } Test Helpers Helper Functions 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) } } Temporary Files and Directories 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 } Golden Files Testing against expected output files stored in 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) } }) } } Mocking with Interfaces Interface-Based Mocking // 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" ) } } Benchmarks Basic Benchmarks 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 Benchmark with Different Sizes 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) } }) } } Memory Allocation Benchmarks 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, "" ) } }) } Fuzzing (Go 1.18+) Basic Fuzz Test func FuzzParseJSON (f *testing.F) { // Add seed corpus f.Add( `{"name": "test"}` )
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.