Test-driven development workflow. Use when user says "write tests", "add tests", "TDD", "test coverage", "unit test", or "integration test".
TDD workflow: Red → Green → Refactor. For language-specific patterns, see references/ directory.
┌─────────────────────────────────────┐
│ 1. RED: Write Failing Test │
│ Test describes desired behavior │
└───────────────┬─────────────────────┘
│ Test fails?
▼
┌─────────────────────────────────────┐
│ 2. GREEN: Make It Pass │
│ Minimum code to pass │
└───────────────┬─────────────────────┘
│ Test passes?
▼
┌─────────────────────────────────────┐
│ 3. REFACTOR: Clean Up │
│ Improve code, tests still pass │
└─────────────────────────────────────┘
Arrange-Act-Assert:
func TestCreateUser_Success(t *testing.T) {
// Arrange
svc := NewService(mockDB)
req := &CreateUserRequest{Name: "Alice"}
// Act
user, err := svc.CreateUser(ctx, req)
// Assert
require.NoError(t, err)
assert.Equal(t, "Alice", user.Name)
}
Test<Function>_<Scenario>
TestCreateUser_Success
TestCreateUser_EmptyName_ReturnsError
TestCreateUser_Duplicate_ReturnsConflict
For multiple cases:
func TestValidateEmail(t *testing.T) {
tests := []struct {
name string
email string
wantErr bool
}{
{"valid", "[email protected]", false},
{"empty", "", true},
{"no_at", "userexample.com", true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
err := ValidateEmail(tt.email)
if tt.wantErr {
assert.Error(t, err)
} else {
assert.NoError(t, err)
}
})
}
}
When fixing a bug:
# Go
go test -cover ./...
# JavaScript
npm test -- --coverage
# Python
pytest --cov=.
Target: 80% on new code, 100% on critical paths.
references/go-testing.md — Go patterns, mocks, subtestsreferences/js-testing.md — Jest, React Testing Libraryreferences/python-testing.md — pytest, fixtures| What | How |
|---|---|
| Naming | Test<Function>_<Scenario> |
| Structure | Arrange-Act-Assert |
| TDD | Red → Green → Refactor |
| Coverage | 80% new code |
| Regression | Write failing test first |