Use when encountering errors or bugs to follow a systematic debugging process instead of jumping to conclusions.
Follow a structured debugging process when encountering errors or unexpected behavior.
Goal: Confirm the error consistently occurs
Example:
# Reproduce the error
make test
# Document output
Error: undefined method 'foo' on line 42
Goal: Narrow down to specific component/function
Example:
# Test individual components
go test ./pkg/auth/handler_test.go -v -run TestLogin
# Isolate to specific function
go test ./pkg/auth -v -run TestLogin/valid_credentials
Goal: Form testable theories about the cause
Examples:
Goal: Verify each hypothesis systematically
Example:
// Test hypothesis 1: nil pointer
if handler.service == nil {
log.Printf("DEBUG: service is nil")
}
// Test hypothesis 2: check types
log.Printf("DEBUG: user type=%T, expected=*User", user)
Goal: Apply fix and verify it resolves the issue
Example:
// Fix: Initialize service before use
func NewHandler() *Handler {
return &Handler{
service: NewAuthService(), // was missing
}
}
Goal: Add tests to prevent regression
Example:
func TestHandlerWithNilService(t *testing.T) {
// Ensure handler initialization is correct
h := NewHandler()
require.NotNil(t, h.service)
}
Don't jump to conclusions:
Don't make multiple changes at once:
Don't assume error messages are wrong:
log.Printf("DEBUG: variable=%+v", variable)
# Go
dlv debug ./cmd/app
# Node
node --inspect-brk app.js
# Python
python -m pdb app.py
# Run single test
go test -v -run TestSpecificFunction
npm test -- --testNamePattern="specific test"
pytest tests/test_file.py::test_function
Problem: Test failing with "unexpected nil pointer"
Step 1 - Reproduce:
make test
# Output: TestLogin: unexpected nil pointer at handler.go:42
Step 2 - Isolate:
go test ./pkg/auth -v -run TestLogin
# Isolated to auth package, Login function
Step 3 - Hypothesize:
Step 4 - Test:
// Add logging at handler.go:42
log.Printf("DEBUG: handler=%+v", handler)
// Output shows handler.service is nil
Step 5 - Fix:
// In NewHandler()
return &Handler{
service: NewAuthService(), // Fix: was missing
}
Step 6 - Prevent:
func TestNewHandler(t *testing.T) {
h := NewHandler()
require.NotNil(t, h.service)
}