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)