Testing Guide
This document explains how to run tests locally to catch CI failures before pushing.
Local Testing Environment
Section titled “Local Testing Environment”We use Docker Compose to match the CI environment exactly. This ensures tests that pass locally will also pass in CI.
# Start Docker services (PostgreSQL + Redis)docker-compose -f docker-compose.test.yml up -d
# Verify services are runningdocker-compose -f docker-compose.test.yml psRunning Tests
Section titled “Running Tests”PDF Shared Package (with Docker services)
Section titled “PDF Shared Package (with Docker services)”# Using the convenience script (recommended)pnpm test:pdf-shared
# Or manually with Docker servicesdocker-compose -f docker-compose.test.yml up -dcd packages/pdf-sharedpython -m pytest tests/ -v --tb=shortOther Test Commands
Section titled “Other Test Commands”# Python tests — packages/pdf-shared + apps/dagster ONLY (requires local setup)pnpm test:python
# Temporal worker tests — NOT run by pnpm test:pythonpnpm --filter @repo/temporal-worker test
# Dagster testspnpm test:dagster
# All Node/TypeScript testspnpm testCleanup
Section titled “Cleanup”# Stop services (keep volumes)docker-compose -f docker-compose.test.yml down
# Stop services and remove volumes (full reset)docker-compose -f docker-compose.test.yml down -vPre-Push Workflow
Section titled “Pre-Push Workflow”CRITICAL: Always run these BEFORE pushing to origin:
# 1. Start Docker servicesdocker-compose -f docker-compose.test.yml up -d
# 2. Run all testspnpm test:pdf-shared # PDF Shared (CI-matched environment)pnpm test:python # Python: packages/pdf-shared + apps/dagsterpnpm --filter @repo/temporal-worker test # Temporal workerpnpm test # All Node/TS tests
# 3. Lint and buildpnpm lint # Includes feature flag checkspnpm build # TypeScript compilation
# 4. If all pass, commit and pushgit add .git commit -m "..."git push origin feat/your-featureTroubleshooting
Section titled “Troubleshooting”PostgreSQL Connection Errors
Section titled “PostgreSQL Connection Errors”If you see “role ‘root’ does not exist”, it means the services aren’t running or haven’t fully initialized.
# Check service statusdocker-compose -f docker-compose.test.yml logs postgres
# Restart servicesdocker-compose -f docker-compose.test.yml restart postgresdocker-compose -f docker-compose.test.yml restart redisPort Already in Use
Section titled “Port Already in Use”docker-compose.test.yml maps PostgreSQL to host port 5433 (${TEST_PG_PORT:-5433}:5432) and Redis to host port 6380 (${TEST_REDIS_PORT:-6380}:6379) so test containers do not collide with local dev containers on 5432/6379. If port 5433 or 6380 is already in use:
# Find and stop conflicting containersdocker psdocker stop <container_id>
# Or override the host ports via env varsTEST_PG_PORT=5434 TEST_REDIS_PORT=6381 docker-compose -f docker-compose.test.yml up -dServices Won’t Start
Section titled “Services Won’t Start”# Full resetdocker-compose -f docker-compose.test.yml down -vdocker-compose -f docker-compose.test.yml up -d
# Check logsdocker-compose -f docker-compose.test.yml logsCI vs Local Testing
Section titled “CI vs Local Testing”What Matches CI
Section titled “What Matches CI”✅ PostgreSQL 16 (alpine) with test user (host port 5433 locally via docker-compose.test.yml)
✅ Redis 7 (host port 6380 locally via docker-compose.test.yml)
✅ Environment variables for mocking external services
✅ Python 3.11 (your local version)
✅ All test dependencies (from uv.lock)
What May Differ
Section titled “What May Differ”⚠️ Your local OS (tests run on Ubuntu in CI)
⚠️ Node version (CI uses Node 22.22.0 per .nvmrc; run nvm use locally)
⚠️ System dependencies (ensure Python 3.11+, git, Docker)
Performance Notes
Section titled “Performance Notes”- First run: ~30s (waiting for services to initialize)
- Subsequent runs: ~2-5s (services already running)
- To speed up: Keep services running between test runs
GitHub Actions CI
Section titled “GitHub Actions CI”Our CI pipeline uses the same services configured in .github/workflows/test-pdf-shared.yml. If tests pass locally with docker-compose, they will pass in CI.
Pre-Push Hook
Section titled “Pre-Push Hook”We enforce testing before push with a Git pre-push hook (.husky/pre-push). This automatically:
- Checks if PDF Shared files changed → runs
pnpm test:pdf-shared - Checks if Python files changed → runs
pnpm lint:python:safe - Checks if TS/JS files changed → runs
pnpm lint && pnpm build
If any check fails, the push is blocked. Fix the issue and try pushing again.
Bypassing the Hook (If Necessary)
Section titled “Bypassing the Hook (If Necessary)”Only use this if you know what you’re doing:
# Force push without running checks (NOT RECOMMENDED)git push --no-verify
# Or disable hook temporarilychmod -x .husky/pre-pushgit pushchmod +x .husky/pre-push⚠️ Warning: Bypassing checks will cause CI failures. Don’t do this unless you have a very good reason.
Questions?
Section titled “Questions?”If a test passes locally but fails in CI, it’s likely an environment difference:
- Check
.github/workflows/test-pdf-shared.ymlfor env vars - Run
docker-compose -f docker-compose.test.yml logsto see service logs - Verify you’re using the correct DATABASE_URL for
docker-compose.test.yml:postgresql://test:test@localhost:5433/test(or5432inside CI service containers)