Files
training-tracker/plans/testing-plan.md
2026-01-19 19:49:47 +01:00

153 lines
4.1 KiB
Markdown

# Backend Testing Plan
## Overview
Add comprehensive tests for the training-tracker backend following Go best practices and the CLAUDE.md guidelines (table-driven tests).
**Scope:** Both unit tests (handlers with mocks) AND integration tests (repositories with testcontainers)
**Plan storage:** Copy this plan to `training-tracker/plans/testing-plan.md`
## Current State
- **No existing tests** - greenfield testing
- 3 packages to test: `api`, `storage`, `models`
- Dependencies: handlers → repositories → database
## Testing Strategy
### 1. Unit Tests for API Handlers
Test HTTP handlers with mocked repositories.
**Files to create:**
- `internal/api/exercises_test.go`
- `internal/api/plans_test.go`
- `internal/api/sessions_test.go`
**Approach:**
- Define repository interfaces
- Create mock implementations
- Use `httptest.NewRecorder()` and `httptest.NewRequest()`
- Table-driven tests for each endpoint
**Test cases per handler:**
- List: empty result, multiple results
- GetByID: found, not found
- Create: valid input, missing required fields, invalid type
- Update: found, not found, validation errors
- Delete: found, not found
### 2. Integration Tests for Storage Layer
Test repositories against real PostgreSQL using testcontainers.
**Files to create:**
- `internal/storage/exercises_test.go`
- `internal/storage/plans_test.go`
- `internal/storage/sessions_test.go`
- `internal/storage/db_test.go`
**Approach:**
- Use `testcontainers-go` to spin up PostgreSQL
- Run migrations before tests
- Test CRUD operations end-to-end
- Test transaction rollback scenarios
**Test cases:**
- CRUD operations for each entity
- Cascading deletes
- Transaction handling in plans (create/update)
- NULL field handling
- Foreign key constraints
### 3. Test File Structure
```
backend/internal/
├── api/
│ ├── exercises_test.go
│ ├── plans_test.go
│ ├── sessions_test.go
│ └── mocks_test.go # Shared mock implementations
├── storage/
│ ├── testhelpers_test.go # Shared test database setup
│ ├── exercises_test.go
│ ├── plans_test.go
│ └── sessions_test.go
└── models/
└── (no tests needed - pure data structures)
```
## Implementation Steps
1. **Create plans folder** and store this plan:
- Create `training-tracker/plans/`
- Copy this plan to `training-tracker/plans/testing-plan.md`
2. **Add test dependencies** to go.mod:
- `github.com/testcontainers/testcontainers-go`
- Use standard library for assertions (no testify)
3. **Create repository interfaces** in `internal/api/`:
- `ExerciseRepository` interface
- `PlanRepository` interface
- `SessionRepository` interface
4. **Create mock implementations** for unit testing handlers
5. **Create test helpers** for integration tests:
- Shared PostgreSQL container setup
- Database cleanup between tests
6. **Write handler unit tests** (table-driven):
- All CRUD operations
- Validation error paths
- Not found scenarios
7. **Write storage integration tests** (table-driven):
- All repository methods
- Edge cases and error conditions
8. **Update CLAUDE.md** with testing instructions
## Files to Modify
- `backend/go.mod` - add test dependencies
- `backend/internal/api/router.go` - extract interfaces for testability
- `backend/CLAUDE.md` - add testing instructions
## Files to Create
- `plans/testing-plan.md` - this plan document
- `backend/internal/api/interfaces.go` - repository interfaces
- `backend/internal/api/mocks_test.go` - mock implementations
- `backend/internal/api/exercises_test.go`
- `backend/internal/api/plans_test.go`
- `backend/internal/api/sessions_test.go`
- `backend/internal/storage/testhelpers_test.go`
- `backend/internal/storage/exercises_test.go`
- `backend/internal/storage/plans_test.go`
- `backend/internal/storage/sessions_test.go`
## Verification
```bash
cd backend
# Run all tests
go test ./...
# Run with verbose output
go test -v ./...
# Run with coverage
go test -cover ./...
# Run only unit tests (fast)
go test -short ./...
# Run specific package
go test -v ./internal/api/...
```