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”If port 5432 or 6379 are already in use:
# Find and stop conflicting containersdocker psdocker stop <container_id>
# Or use different ports (edit docker-compose.test.yml)Services 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
✅ Redis 7
✅ 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 20, you may have different) ⚠️ 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:
postgresql://test:test@localhost:5432/test