Skip to content

Testing Guide

This document explains how to run tests locally to catch CI failures before pushing.

We use Docker Compose to match the CI environment exactly. This ensures tests that pass locally will also pass in CI.

Terminal window
# Start Docker services (PostgreSQL + Redis)
docker-compose -f docker-compose.test.yml up -d
# Verify services are running
docker-compose -f docker-compose.test.yml ps
Terminal window
# Using the convenience script (recommended)
pnpm test:pdf-shared
# Or manually with Docker services
docker-compose -f docker-compose.test.yml up -d
cd packages/pdf-shared
python -m pytest tests/ -v --tb=short
Terminal window
# Python tests — packages/pdf-shared + apps/dagster ONLY (requires local setup)
pnpm test:python
# Temporal worker tests — NOT run by pnpm test:python
pnpm --filter @repo/temporal-worker test
# Dagster tests
pnpm test:dagster
# All Node/TypeScript tests
pnpm test
Terminal window
# 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 -v

CRITICAL: Always run these BEFORE pushing to origin:

Terminal window
# 1. Start Docker services
docker-compose -f docker-compose.test.yml up -d
# 2. Run all tests
pnpm test:pdf-shared # PDF Shared (CI-matched environment)
pnpm test:python # Python: packages/pdf-shared + apps/dagster
pnpm --filter @repo/temporal-worker test # Temporal worker
pnpm test # All Node/TS tests
# 3. Lint and build
pnpm lint # Includes feature flag checks
pnpm build # TypeScript compilation
# 4. If all pass, commit and push
git add .
git commit -m "..."
git push origin feat/your-feature

If you see “role ‘root’ does not exist”, it means the services aren’t running or haven’t fully initialized.

Terminal window
# Check service status
docker-compose -f docker-compose.test.yml logs postgres
# Restart services
docker-compose -f docker-compose.test.yml restart postgres
docker-compose -f docker-compose.test.yml restart redis

If port 5432 or 6379 are already in use:

Terminal window
# Find and stop conflicting containers
docker ps
docker stop <container_id>
# Or use different ports (edit docker-compose.test.yml)
Terminal window
# Full reset
docker-compose -f docker-compose.test.yml down -v
docker-compose -f docker-compose.test.yml up -d
# Check logs
docker-compose -f docker-compose.test.yml logs

✅ 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)

⚠️ 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)

  • First run: ~30s (waiting for services to initialize)
  • Subsequent runs: ~2-5s (services already running)
  • To speed up: Keep services running between test runs

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.

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.

Only use this if you know what you’re doing:

Terminal window
# Force push without running checks (NOT RECOMMENDED)
git push --no-verify
# Or disable hook temporarily
chmod -x .husky/pre-push
git push
chmod +x .husky/pre-push

⚠️ Warning: Bypassing checks will cause CI failures. Don’t do this unless you have a very good reason.

If a test passes locally but fails in CI, it’s likely an environment difference:

  1. Check .github/workflows/test-pdf-shared.yml for env vars
  2. Run docker-compose -f docker-compose.test.yml logs to see service logs
  3. Verify you’re using the correct DATABASE_URL: postgresql://test:test@localhost:5432/test