golang-testing
Go testing best practices including table-driven tests, test helpers, benchmarking, race detection, coverage analysis, and integration testing patterns. Use when writing or improving Go tests.
About this skill
This skill empowers AI agents to generate or refactor high-quality Go tests following established best practices. It emphasizes the idiomatic Go testing framework using `go test` and promotes table-driven tests for comprehensive scenario coverage. Beyond basic unit testing, the skill incorporates advanced techniques such as writing test helpers, performance benchmarking, detecting data races, analyzing test coverage, and implementing effective integration testing patterns. Designed to be a comprehensive resource for enhancing Go test suites, it ensures the generated Go test code is reliable, maintainable, and aligned with industry standards for production-ready Go applications.
Best use case
Generating new test cases for existing Go functions or packages. Refactoring or improving the quality and coverage of existing Go test files. Adding performance benchmarks to critical Go code paths. Ensuring new Go code adheres to testing best practices from the outset. Identifying potential race conditions in Go concurrency patterns and suggesting tests for them. Developing integration tests for Go services and APIs.
Go testing best practices including table-driven tests, test helpers, benchmarking, race detection, coverage analysis, and integration testing patterns. Use when writing or improving Go tests.
Well-structured, idiomatic Go test code using the standard `testing` package. Comprehensive test cases covering various scenarios via table-driven tests. Benchmarking functions to measure code performance. Effective test helpers to reduce boilerplate and improve test readability. Guidance on detecting race conditions and analyzing test coverage. Patterns for effective integration tests, enhancing application reliability.
Practical example
Example input
Generate Go tests for the following `CalculateDiscount` function. It should include table-driven tests covering positive, zero, and edge-case discount percentages. Also, add a benchmark for its performance.
```go
package main
import "fmt"
func CalculateDiscount(originalPrice float64, discountPercent float64) (float64, error) {
if discountPercent < 0 || discountPercent > 100 {
return 0, fmt.Errorf("discount percentage must be between 0 and 100")
}
discountAmount := originalPrice * (discountPercent / 100)
finalPrice := originalPrice - discountAmount
return finalPrice, nil
}
```Example output
```go
package main
import (
"math"
"testing"
)
// Helper function to compare floats with a tolerance
func assertFloatEquals(t *testing.T, got, want float64, msg string) {
t.Helper()
if math.Abs(got-want) > 0.001 { // Using a small tolerance for float comparison
t.Errorf("%s: got %f, want %f", msg, got, want)
}
}
func TestCalculateDiscount(t *testing.T) {
tests := []struct {
name string
originalPrice float64
discountPercent float64
wantFinalPrice float64
wantErr bool
}{
{
name: "valid discount 10%",
originalPrice: 100.0,
discountPercent: 10.0,
wantFinalPrice: 90.0,
wantErr: false,
},
{
name: "valid discount 0%",
originalPrice: 100.0,
discountPercent: 0.0,
wantFinalPrice: 100.0,
wantErr: false,
},
{
name: "valid discount 100%",
originalPrice: 100.0,
discountPercent: 100.0,
wantFinalPrice: 0.0,
wantErr: false,
},
{
name: "invalid discount negative",
originalPrice: 100.0,
discountPercent: -5.0,
wantFinalPrice: 0.0,
wantErr: true,
},
{
name: "invalid discount over 100%",
originalPrice: 100.0,
discountPercent: 105.0,
wantFinalPrice: 0.0,
wantErr: true,
},
{
name: "zero original price",
originalPrice: 0.0,
discountPercent: 10.0,
wantFinalPrice: 0.0,
wantErr: false,
},
{
name: "fractional discount",
originalPrice: 99.99,
discountPercent: 12.5,
wantFinalPrice: 87.49125,
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
gotFinalPrice, err := CalculateDiscount(tt.originalPrice, tt.discountPercent)
if (err != nil) != tt.wantErr {
t.Errorf("CalculateDiscount() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !tt.wantErr {
assertFloatEquals(t, gotFinalPrice, tt.wantFinalPrice, "CalculateDiscount() final price mismatch")
}
})
}
}
func BenchmarkCalculateDiscount(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
_, _ = CalculateDiscount(100.0, 10.0)
}
}
```When to use this skill
- When asked to 'Write Go tests for `funcName` adhering to table-driven patterns.'
- When prompted to 'Improve the test coverage for this Go package.'
- When requesting to 'Add benchmarks for `functionX` in `fileName.go`.'
- When needing to 'Generate integration tests for this Go service's API endpoints.'
When not to use this skill
- When the task does not involve Go language or testing (e.g., Python development, general writing).
- For generating production Go application code directly (this skill is focused on testing).
- If the primary goal is to set up a CI/CD pipeline for Go testing (though it provides the content for tests within it).
Installation
Claude Code / Cursor / Codex
Manual Installation
- Download SKILL.md from GitHub
- Place it in
.claude/skills/golang-testing/SKILL.mdinside your project - Restart your AI agent — it will auto-discover the skill
How golang-testing Compares
| Feature / Agent | golang-testing | Standard Approach |
|---|---|---|
| Platform Support | Claude | Limited / Varies |
| Context Awareness | High | Baseline |
| Installation Complexity | easy | N/A |
Frequently Asked Questions
What does this skill do?
Go testing best practices including table-driven tests, test helpers, benchmarking, race detection, coverage analysis, and integration testing patterns. Use when writing or improving Go tests.
Which AI agents support this skill?
This skill is designed for Claude.
How difficult is it to install?
The installation complexity is rated as easy. You can find the installation instructions above.
Where can I find the source code?
You can find the source code on GitHub using the link provided at the top of the page.
Related Guides
AI Agents for Coding
Browse AI agent skills for coding, debugging, testing, refactoring, code review, and developer workflows across Claude, Cursor, and Codex.
Best AI Skills for Claude
Explore the best AI skills for Claude and Claude Code across coding, research, workflow automation, documentation, and agent operations.
AI Agent for Product Research
Browse AI agent skills for product research, competitive analysis, customer discovery, and structured product decision support.
SKILL.md Source
# Go Testing
> This skill provides comprehensive Go testing patterns extending common testing principles with Go-specific idioms.
## Testing Framework
Use the standard `go test` with **table-driven tests** as the primary pattern.
### Table-Driven Tests
The idiomatic Go testing pattern:
```go
func TestValidateEmail(t *testing.T) {
tests := []struct {
name string
email string
wantErr bool
}{
{
name: "valid email",
email: "user@example.com",
wantErr: false,
},
{
name: "missing @",
email: "userexample.com",
wantErr: true,
},
{
name: "empty string",
email: "",
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
err := ValidateEmail(tt.email)
if (err != nil) != tt.wantErr {
t.Errorf("ValidateEmail(%q) error = %v, wantErr %v",
tt.email, err, tt.wantErr)
}
})
}
}
```
**Benefits:**
- Easy to add new test cases
- Clear test case documentation
- Parallel test execution with `t.Parallel()`
- Isolated subtests with `t.Run()`
## Test Helpers
Use `t.Helper()` to mark helper functions:
```go
func assertNoError(t *testing.T, err error) {
t.Helper()
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
}
func assertEqual(t *testing.T, got, want interface{}) {
t.Helper()
if !reflect.DeepEqual(got, want) {
t.Errorf("got %v, want %v", got, want)
}
}
```
**Benefits:**
- Correct line numbers in test failures
- Reusable test utilities
- Cleaner test code
## Test Fixtures
Use `t.Cleanup()` for resource cleanup:
```go
func testDB(t *testing.T) *sql.DB {
t.Helper()
db, err := sql.Open("sqlite3", ":memory:")
if err != nil {
t.Fatalf("failed to open test db: %v", err)
}
// Cleanup runs after test completes
t.Cleanup(func() {
if err := db.Close(); err != nil {
t.Errorf("failed to close db: %v", err)
}
})
return db
}
func TestUserRepository(t *testing.T) {
db := testDB(t)
repo := NewUserRepository(db)
// ... test logic
}
```
## Race Detection
Always run tests with the `-race` flag to detect data races:
```bash
go test -race ./...
```
**In CI/CD:**
```yaml
- name: Test with race detector
run: go test -race -timeout 5m ./...
```
**Why:**
- Detects concurrent access bugs
- Prevents production race conditions
- Minimal performance overhead in tests
## Coverage Analysis
### Basic Coverage
```bash
go test -cover ./...
```
### Detailed Coverage Report
```bash
go test -coverprofile=coverage.out ./...
go tool cover -html=coverage.out
```
### Coverage Thresholds
```bash
# Fail if coverage below 80%
go test -cover ./... | grep -E 'coverage: [0-7][0-9]\.[0-9]%' && exit 1
```
## Benchmarking
```go
func BenchmarkValidateEmail(b *testing.B) {
email := "user@example.com"
b.ResetTimer()
for i := 0; i < b.N; i++ {
ValidateEmail(email)
}
}
```
**Run benchmarks:**
```bash
go test -bench=. -benchmem
```
**Compare benchmarks:**
```bash
go test -bench=. -benchmem > old.txt
# make changes
go test -bench=. -benchmem > new.txt
benchstat old.txt new.txt
```
## Mocking
### Interface-Based Mocking
```go
type UserRepository interface {
GetUser(id string) (*User, error)
}
type mockUserRepository struct {
users map[string]*User
err error
}
func (m *mockUserRepository) GetUser(id string) (*User, error) {
if m.err != nil {
return nil, m.err
}
return m.users[id], nil
}
func TestUserService(t *testing.T) {
mock := &mockUserRepository{
users: map[string]*User{
"1": {ID: "1", Name: "Alice"},
},
}
service := NewUserService(mock)
// ... test logic
}
```
## Integration Tests
### Build Tags
```go
//go:build integration
// +build integration
package user_test
func TestUserRepository_Integration(t *testing.T) {
// ... integration test
}
```
**Run integration tests:**
```bash
go test -tags=integration ./...
```
### Test Containers
```go
func TestWithPostgres(t *testing.T) {
if testing.Short() {
t.Skip("skipping integration test")
}
// Setup test container
ctx := context.Background()
container, err := testcontainers.GenericContainer(ctx, ...)
assertNoError(t, err)
t.Cleanup(func() {
container.Terminate(ctx)
})
// ... test logic
}
```
## Test Organization
### File Structure
```
package/
├── user.go
├── user_test.go # Unit tests
├── user_integration_test.go # Integration tests
└── testdata/ # Test fixtures
└── users.json
```
### Package Naming
```go
// Black-box testing (external perspective)
package user_test
// White-box testing (internal access)
package user
```
## Common Patterns
### Testing HTTP Handlers
```go
func TestUserHandler(t *testing.T) {
req := httptest.NewRequest("GET", "/users/1", nil)
rec := httptest.NewRecorder()
handler := NewUserHandler(mockRepo)
handler.ServeHTTP(rec, req)
assertEqual(t, rec.Code, http.StatusOK)
}
```
### Testing with Context
```go
func TestWithTimeout(t *testing.T) {
ctx, cancel := context.WithTimeout(context.Background(), 100*time.Millisecond)
defer cancel()
err := SlowOperation(ctx)
if !errors.Is(err, context.DeadlineExceeded) {
t.Errorf("expected timeout error, got %v", err)
}
}
```
## Best Practices
1. **Use `t.Parallel()`** for independent tests
2. **Use `testing.Short()`** to skip slow tests
3. **Use `t.TempDir()`** for temporary directories
4. **Use `t.Setenv()`** for environment variables
5. **Avoid `init()`** in test files
6. **Keep tests focused** - one behavior per test
7. **Use meaningful test names** - describe what's being tested
## When to Use This Skill
- Writing new Go tests
- Improving test coverage
- Setting up test infrastructure
- Debugging flaky tests
- Optimizing test performance
- Implementing integration testsRelated Skills
swift-protocol-di-testing
基于协议的依赖注入,用于可测试的Swift代码——使用聚焦协议和Swift Testing模拟文件系统、网络和外部API。
perl-testing
使用Test2::V0、Test::More、prove runner、模拟、Devel::Cover覆盖率和TDD方法的Perl测试模式。
rust-testing
Rust testing patterns including unit tests, integration tests, async testing, property-based testing, mocking, and coverage. Follows TDD methodology.
kotlin-testing
Kotest, MockK, coroutine testi, property-based testing ve Kover coverage ile Kotlin test kalıpları. İdiomatic Kotlin uygulamalarıyla TDD metodolojisini takip eder.
cpp-testing
C++ テストの作成/更新/修正、GoogleTest/CTest の設定、失敗またはフレーキーなテストの診断、カバレッジ/サニタイザーの追加時にのみ使用します。
python-testing
Python testing best practices using pytest including fixtures, parametrization, mocking, coverage analysis, async testing, and test organization. Use when writing or improving Python tests.
golang-patterns
Go-specific design patterns and best practices including functional options, small interfaces, dependency injection, concurrency patterns, error handling, and package organization. Use when working with Go code to apply idiomatic Go patterns.
workspace-surface-audit
Audit the active repo, MCP servers, plugins, connectors, env surfaces, and harness setup, then recommend the highest-value ECC-native skills, hooks, agents, and operator workflows. Use when the user wants help setting up Claude Code or understanding what capabilities are actually available in their environment.
safety-guard
Use this skill to prevent destructive operations when working on production systems or running agents autonomously.
repo-scan
Cross-stack source code asset audit — classifies every file, detects embedded third-party libraries, and delivers actionable four-level verdicts per module with interactive HTML reports.
project-flow-ops
Operate execution flow across GitHub and Linear by triaging issues and pull requests, linking active work, and keeping GitHub public-facing while Linear remains the internal execution layer. Use when the user wants backlog control, PR triage, or GitHub-to-Linear coordination.
manim-video
Build reusable Manim explainers for technical concepts, graphs, system diagrams, and product walkthroughs, then hand off to the wider ECC video stack if needed. Use when the user wants a clean animated explainer rather than a generic talking-head script.