A community based topic aggregation platform built on atproto
1# Coves Testing Guide 2 3This document explains how testing works in Coves, including setup, running tests, and understanding the test infrastructure. 4 5## Overview 6 7Coves uses a unified testing approach with: 8- **Single configuration file**: [.env.dev](.env.dev) for all environments (dev + test) 9- **Isolated test database**: PostgreSQL on port 5434 (separate from dev on 5433) 10- **Makefile commands**: Simple `make test` command handles everything 11- **Docker Compose profiles**: Test database spins up automatically 12 13## Quick Start 14 15```bash 16# Run all tests (starts test DB, runs migrations, executes tests) 17make test 18 19# Reset test database (clean slate) 20make test-db-reset 21 22# Stop test database 23make test-db-stop 24``` 25 26## Test Infrastructure 27 28### Configuration (.env.dev) 29 30All test configuration lives in [.env.dev](.env.dev): 31 32```bash 33# Test Database Configuration 34POSTGRES_TEST_DB=coves_test 35POSTGRES_TEST_USER=test_user 36POSTGRES_TEST_PASSWORD=test_password 37POSTGRES_TEST_PORT=5434 38``` 39 40**No separate `.env.test` file needed!** Everything is in `.env.dev`. 41 42### Test Database 43 44The test database runs in Docker via [docker-compose.dev.yml](docker-compose.dev.yml): 45 46- **Service**: `postgres-test` (profile: `test`) 47- **Port**: 5434 (separate from dev database on 5433) 48- **Automatic startup**: The Makefile handles starting/stopping 49- **Isolated data**: Completely separate from development database 50 51### Running Tests Manually 52 53If you need to run tests without the Makefile: 54 55```bash 56# 1. Load environment variables 57set -a && source .env.dev && set +a 58 59# 2. Start test database 60docker-compose -f docker-compose.dev.yml --env-file .env.dev --profile test up -d postgres-test 61 62# 3. Wait for it to be ready 63sleep 3 64 65# 4. Run migrations 66goose -dir internal/db/migrations postgres \ 67 "postgresql://$POSTGRES_TEST_USER:$POSTGRES_TEST_PASSWORD@localhost:$POSTGRES_TEST_PORT/$POSTGRES_TEST_DB?sslmode=disable" up 68 69# 5. Run tests 70go test ./... -v 71 72# 6. Stop test database (optional) 73docker-compose -f docker-compose.dev.yml --env-file .env.dev --profile test stop postgres-test 74``` 75 76**Note**: The Makefile automatically loads `.env.dev` variables, so `make test` is simpler than running manually. 77 78## Test Types 79 80### 1. Unit Tests 81 82Test individual components in isolation. 83 84**Note**: Unit tests will be added as needed. Currently focusing on integration tests. 85 86```bash 87# Run unit tests for a specific package (when available) 88go test -v ./internal/core/users/... 89``` 90 91### 2. Integration Tests 92 93Test full request/response flows with a real database. 94 95**Location**: [tests/integration/](tests/integration/) 96 97**How they work**: 98- Start test database 99- Run migrations 100- Execute HTTP requests against real handlers 101- Verify responses 102 103**Example**: [tests/integration/integration_test.go](tests/integration/integration_test.go) 104 105```bash 106# Run integration tests 107make test 108# or 109go test -v ./tests/integration/... 110``` 111 112### 3. Lexicon Validation Tests 113 114Validate AT Protocol Lexicon schemas and test data. 115 116**Components**: 117- **Schemas**: [internal/atproto/lexicon/](internal/atproto/lexicon/) - 57 lexicon schema files 118- **Test Data**: [tests/lexicon-test-data/](tests/lexicon-test-data/) - Example records for validation 119- **Validator**: [cmd/validate-lexicon/](cmd/validate-lexicon/) - Validation tool 120- **Library**: [internal/validation/](internal/validation/) - Validation helpers 121 122**Running validation**: 123 124```bash 125# Full validation (schemas + test data) 126go run cmd/validate-lexicon/main.go 127 128# Schemas only (skip test data) 129go run cmd/validate-lexicon/main.go --schemas-only 130 131# Verbose output 132go run cmd/validate-lexicon/main.go -v 133 134# Strict mode 135go run cmd/validate-lexicon/main.go --strict 136``` 137 138**Test data naming convention**: 139- `*-valid*.json` - Should pass validation 140- `*-invalid-*.json` - Should fail validation (tests error detection) 141 142**Current coverage** (as of last update): 143- ✅ social.coves.actor.profile 144- ✅ social.coves.community.profile 145- ✅ social.coves.post.record 146- ✅ social.coves.interaction.vote 147- ✅ social.coves.moderation.ban 148 149## Database Migrations 150 151Migrations are managed with [goose](https://github.com/pressly/goose) and stored in [internal/db/migrations/](internal/db/migrations/). 152 153### Running Migrations 154 155```bash 156# Development database 157make db-migrate 158 159# Test database (automatically run by `make test`) 160make test-db-reset 161``` 162 163### Creating Migrations 164 165```bash 166# Create a new migration 167goose -dir internal/db/migrations create migration_name sql 168 169# This creates: 170# internal/db/migrations/YYYYMMDDHHMMSS_migration_name.sql 171``` 172 173### Migration Best Practices 174 175- **Always test migrations** on test database first 176- **Write both Up and Down** migrations 177- **Keep migrations atomic** - one logical change per migration 178- **Test rollback** - verify the Down migration works 179- **Don't modify old migrations** - create new ones instead 180 181## Test Database Management 182 183### Fresh Start 184 185```bash 186# Complete reset (deletes all data) 187make test-db-reset 188``` 189 190### Connecting to Test Database 191 192```bash 193# Using psql 194PGPASSWORD=test_password psql -h localhost -p 5434 -U test_user -d coves_test 195 196# Using docker exec 197docker exec -it coves-test-postgres psql -U test_user -d coves_test 198``` 199 200### Inspecting Test Data 201 202```sql 203-- List all tables 204\dt 205 206-- View table schema 207\d table_name 208 209-- Query data 210SELECT * FROM users; 211 212-- Check migrations 213SELECT * FROM goose_db_version; 214``` 215 216## Writing Tests 217 218### Integration Test Template 219 220```go 221package integration 222 223import ( 224 "testing" 225 // ... imports 226) 227 228func TestYourFeature(t *testing.T) { 229 db := setupTestDB(t) 230 defer db.Close() 231 232 // Wire up dependencies 233 repo := postgres.NewYourRepository(db) 234 service := yourpackage.NewYourService(repo) 235 236 // Create test router 237 r := chi.NewRouter() 238 r.Mount("/api/path", routes.YourRoutes(service)) 239 240 // Make request 241 req := httptest.NewRequest("GET", "/api/path", nil) 242 w := httptest.NewRecorder() 243 r.ServeHTTP(w, req) 244 245 // Assert 246 if w.Code != http.StatusOK { 247 t.Errorf("Expected 200, got %d", w.Code) 248 } 249} 250``` 251 252### Test Helper: setupTestDB 253 254The `setupTestDB` function (in [tests/integration/integration_test.go](tests/integration/integration_test.go)): 255- Reads config from environment variables (set by `.env.dev`) 256- Connects to test database 257- Runs migrations 258- Cleans up test data 259- Returns ready-to-use `*sql.DB` 260 261## Common Test Commands 262 263```bash 264# Run all tests 265make test 266 267# Run specific test package 268go test -v ./internal/core/users/... 269 270# Run specific test 271go test -v ./tests/integration/... -run TestCreateUser 272 273# Run with coverage 274go test -v -cover ./... 275 276# Run with race detector 277go test -v -race ./... 278 279# Verbose output 280go test -v ./... 281 282# Clean and run 283make test-db-reset && make test 284``` 285 286## Troubleshooting 287 288### Test database won't start 289 290```bash 291# Check if port 5434 is in use 292lsof -i :5434 293 294# Check container logs 295docker logs coves-test-postgres 296 297# Nuclear reset 298docker-compose -f docker-compose.dev.yml --profile test down -v 299make test-db-reset 300``` 301 302### Migrations failing 303 304```bash 305# Load environment and check migration status 306set -a && source .env.dev && set +a 307goose -dir internal/db/migrations postgres \ 308 "postgresql://$POSTGRES_TEST_USER:$POSTGRES_TEST_PASSWORD@localhost:$POSTGRES_TEST_PORT/$POSTGRES_TEST_DB?sslmode=disable" status 309 310# Reset and retry 311make test-db-reset 312``` 313 314### Tests can't connect to database 315 316```bash 317# Verify test database is running 318docker ps | grep coves-test-postgres 319 320# Verify environment variables 321set -a && source .env.dev && set +a && echo "Test DB Port: $POSTGRES_TEST_PORT" 322 323# Test connection manually 324PGPASSWORD=test_password psql -h localhost -p 5434 -U test_user -d coves_test -c "SELECT 1" 325``` 326 327### Lexicon validation errors 328 329```bash 330# Check schema syntax 331cat internal/atproto/lexicon/path/to/schema.json | jq . 332 333# Validate specific schema 334go run cmd/validate-lexicon/main.go -v 335 336# Check test data format 337cat tests/lexicon-test-data/your-test.json | jq . 338``` 339 340## Best Practices 341 342### Test Organization 343- ✅ Unit tests live next to the code they test (`*_test.go`) 344- ✅ Integration tests live in `tests/integration/` 345- ✅ Test data lives in `tests/lexicon-test-data/` 346- ✅ One test file per feature/endpoint 347 348### Test Data 349- ✅ Use `.test` handles for test users (e.g., `alice.test`) (auto-cleaned by setupTestDB) 350- ✅ Clean up data in tests (or rely on setupTestDB cleanup) 351- ✅ Don't rely on specific test execution order 352- ✅ Each test should be independent 353 354### Database Tests 355- ✅ Always use the test database (port 5434) 356- ✅ Never connect to development database (port 5433) in tests 357- ✅ Use transactions for fast test cleanup (where applicable) 358- ✅ Test with realistic data sizes 359 360### Lexicon Tests 361- ✅ Create both valid and invalid test cases 362- ✅ Cover all required fields 363- ✅ Test edge cases (empty strings, max lengths, etc.) 364- ✅ Update tests when schemas change 365 366## CI/CD Integration 367 368When setting up CI/CD, the test pipeline should: 369 370```yaml 371# Example GitHub Actions workflow 372steps: 373 - name: Start test database 374 run: | 375 docker-compose -f docker-compose.dev.yml --env-file .env.dev --profile test up -d postgres-test 376 sleep 5 377 378 - name: Run migrations 379 run: make test-db-migrate # (add this to Makefile if needed) 380 381 - name: Run tests 382 run: make test 383 384 - name: Cleanup 385 run: docker-compose -f docker-compose.dev.yml --profile test down -v 386``` 387 388## Related Documentation 389 390- [Makefile](Makefile) - All test commands 391- [.env.dev](.env.dev) - Test configuration 392- [docker-compose.dev.yml](docker-compose.dev.yml) - Test database setup 393- [LOCAL_DEVELOPMENT.md](docs/LOCAL_DEVELOPMENT.md) - Full development setup 394- [CLAUDE.md](CLAUDE.md) - Build guidelines 395 396## Getting Help 397 398If tests are failing: 3991. Check [Troubleshooting](#troubleshooting) section above 4002. Verify `.env.dev` has correct test database config 4013. Run `make test-db-reset` for a clean slate 4024. Check test database logs: `docker logs coves-test-postgres` 403 404For questions about: 405- **Test infrastructure**: This document 406- **AT Protocol testing**: [ATPROTO_GUIDE.md](ATPROTO_GUIDE.md) 407- **Development setup**: [LOCAL_DEVELOPMENT.md](docs/LOCAL_DEVELOPMENT.md)