Test Function Patterns
Basic Test Function Pattern
Simple Test Function
func TestAdd(t *testing.T) {
result := Add(2, 3)
if result != 5 {
t.Errorf("Expected 5, got %d", result)
}
}
Table-Driven Tests
Implementing Table-Driven Tests
func TestCalculations(t *testing.T) {
testCases := []struct {
name string
input int
expected int
}{
{"Positive Number", 5, 25},
{"Zero", 0, 0},
{"Negative Number", -3, 9},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
result := Square(tc.input)
if result != tc.expected {
t.Errorf("Expected %d, got %d", tc.expected, result)
}
})
}
}
Subtests and Test Groups
Organizing Complex Tests
func TestUserOperations(t *testing.T) {
t.Run("CreateUser", func(t *testing.T) {
// User creation tests
})
t.Run("UpdateUser", func(t *testing.T) {
// User update tests
})
t.Run("DeleteUser", func(t *testing.T) {
// User deletion tests
})
}
Test Patterns Comparison
Pattern |
Complexity |
Readability |
Flexibility |
Simple Test |
Low |
High |
Low |
Table-Driven |
Medium |
Medium |
High |
Subtest |
High |
High |
Very High |
Mocking and Dependency Injection
graph TD
A[Test Function] --> B{Requires External Dependency}
B -->|Yes| C[Create Mock Object]
B -->|No| D[Direct Testing]
C --> E[Inject Mock into Function]
E --> F[Perform Test]
Advanced Test Techniques
Parameterized Tests
func TestMultiply(t *testing.T) {
testCases := []struct {
a, b, expected int
}{
{2, 3, 6},
{0, 5, 0},
{-2, 4, -8},
}
for _, tc := range testCases {
result := Multiply(tc.a, tc.b)
if result != tc.expected {
t.Errorf("Multiply(%d, %d) = %d; want %d",
tc.a, tc.b, result, tc.expected)
}
}
}
LabEx Testing Recommendations
- Prefer table-driven tests for complex scenarios
- Use subtests for better test organization
- Implement dependency injection for testability
- Keep test functions focused and concise
Error Handling in Tests
Handling Different Error Scenarios
func TestErrorHandling(t *testing.T) {
t.Run("ExpectedError", func(t *testing.T) {
_, err := SomeFunction()
if err == nil {
t.Error("Expected an error, got nil")
}
})
t.Run("UnexpectedError", func(t *testing.T) {
result, err := AnotherFunction()
if err != nil {
t.Errorf("Unexpected error: %v", err)
}
// Additional assertions
})
}
By mastering these test function patterns, developers can create comprehensive and maintainable test suites in Go.