AI Skill Report Card
Generated Skill
YAML--- name: testing-go-apis description: Creates comprehensive test suites for Go APIs including unit, integration, and end-to-end tests. Use when building or improving test coverage for Go backend services. ---
Quick Start
Go// Basic API test structure func TestUserHandler(t *testing.T) { // Setup test server router := setupTestRouter() server := httptest.NewServer(router) defer server.Close() // Test case resp, err := http.Get(server.URL + "/api/users/1") assert.NoError(t, err) assert.Equal(t, http.StatusOK, resp.StatusCode) }
Recommendation▾
Consider adding more specific examples
Workflow
Test Development Process:
Progress:
- Analyze API endpoints and business logic
- Write unit tests for individual functions
- Create integration tests for database interactions
- Build E2E tests for complete user flows
- Set up test data fixtures and cleanup
- Configure CI/CD test pipeline
1. Unit Tests
- Test individual handlers, services, and utilities
- Mock external dependencies (database, APIs)
- Focus on business logic validation
2. Integration Tests
- Test with real database (use test containers)
- Verify data persistence and retrieval
- Test middleware and authentication flows
3. E2E Tests
- Full request-response cycles
- Test complete user journeys
- Validate API contracts and responses
Recommendation▾
Include edge cases
Examples
Example 1: Unit Test
Gofunc TestValidateUser(t *testing.T) { tests := []struct { name string user User wantErr bool }{ {"valid user", User{Email: "test@example.com", Name: "John"}, false}, {"invalid email", User{Email: "invalid", Name: "John"}, true}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { err := ValidateUser(tt.user) assert.Equal(t, tt.wantErr, err != nil) }) } }
Example 2: Integration Test
Gofunc TestUserRepository_Create(t *testing.T) { // Setup test database db := setupTestDB(t) repo := NewUserRepository(db) user := &User{Email: "test@example.com", Name: "John"} err := repo.Create(user) assert.NoError(t, err) assert.NotZero(t, user.ID) // Verify in database found, err := repo.GetByID(user.ID) assert.NoError(t, err) assert.Equal(t, user.Email, found.Email) }
Example 3: E2E Test
Gofunc TestCreateUserFlow(t *testing.T) { server := setupTestServer() client := &http.Client{} // Create user payload := `{"email":"test@example.com","name":"John"}` resp := makeRequest(t, client, "POST", server.URL+"/api/users", payload) assert.Equal(t, http.StatusCreated, resp.StatusCode) var user User json.NewDecoder(resp.Body).Decode(&user) // Verify user exists resp = makeRequest(t, client, "GET", server.URL+"/api/users/"+user.ID, "") assert.Equal(t, http.StatusOK, resp.StatusCode) }
Best Practices
Test Structure:
- Use table-driven tests for multiple scenarios
- Follow AAA pattern: Arrange, Act, Assert
- Use testify/assert for cleaner assertions
Test Data:
- Use factories or builders for test objects
- Implement proper cleanup with
t.Cleanup() - Use separate test database/environment
Mocking:
Go// Use interfaces for easy mocking type UserService interface { GetUser(id string) (*User, error) } // Mock in tests mockService := &MockUserService{} mockService.On("GetUser", "123").Return(&User{}, nil)
Test Organization:
- Separate files:
handler_test.go,service_test.go - Use build tags for integration tests:
//go:build integration - Group related tests in subtests
Common Pitfalls
Don't:
- Test implementation details, focus on behavior
- Use production database for tests
- Write tests that depend on external services without mocking
- Ignore test data cleanup leading to flaky tests
- Mix unit and integration tests in same file without clear separation
Avoid:
- Hard-coded test values that break easily
- Tests that require specific execution order
- Overly complex test setup that obscures the actual test
- Testing framework code instead of your business logic