Testing Overview
Testing pyramid, tools by framework, where each test runs, and the team's CI gate flow.
Quality is enforced at every stage — from a developer's laptop through Alpha, Beta, and Production. This page defines our testing strategy: the pyramid, the tools per app framework, where each test runs, and where Playwright E2E and Performance & Load testing fit.
Testing pyramid
| Layer | Purpose | CI trigger | Speed |
|---|---|---|---|
| Unit | Pure functions, components in isolation | Every PR to alpha, beta, prod | Fast (seconds) |
| Integration | Modules + real DB / API boundaries | Every PR to alpha, beta, prod | Medium (minutes) |
| E2E | Critical user journeys in a real browser | PR → Alpha preview, then Beta after merge | Slower (minutes) |
| Performance / Load | Latency, throughput, soak, realtime fan-out | Scheduled + pre-release on Beta | Long (minutes–hours) |
| Manual QA | Exploratory + sign-off | Beta, before promotion | Human |
Where tests run
Each test type runs in specific places (local, GitHub Actions, or manual) and against specific environments. Use this matrix to know what executes where.
| Test type | Local (laptop) | GitHub Actions (CI) | Manual | Target environment |
|---|---|---|---|---|
| Unit | On demand | ✅ Every PR → alpha/beta/prod | — | N/A (no deploy) |
| Integration | With test DB (Docker) | ✅ Every PR → alpha/beta/prod | — | Ephemeral test DB |
| E2E (smoke) | localhost | ✅ On PR | — | Alpha preview URL |
| E2E (full) | On demand | ✅ On merge to beta | — | Beta |
| Performance / Load | Quick baseline | ✅ Nightly schedule | ✅ Pre-release | Beta (never Prod) |
| Manual QA | — | — | ✅ QA test plan | Beta |
| Synthetic monitoring | — | ✅ Continuous (cron) | — | Production |
See Environments for how Alpha → Beta → Prod promotion works, and Playwright CI for the actual workflow files.
Tools by app framework
Pick tools based on the app's framework. Unit/component tools differ per stack; Playwright is the single E2E standard across all web apps so end-to-end tests look the same everywhere.
| Framework | Unit | Component | Integration | E2E |
|---|---|---|---|---|
| Angular | Jasmine + Karma (default) · Vitest (modern, experimental) | Angular TestBed (+ Testing Library) | TestBed + HttpTestingController | Playwright |
| React + Next.js | Vitest / Jest | React Testing Library | Vitest + MSW | Playwright |
| React + Vite | Vitest | React Testing Library | Vitest + MSW | Playwright |
| React Native | Jest | RN Testing Library | Jest + MSW | Detox / Maestro |
| Node.js (Express + TS) | Vitest (recommended) · Jest (legacy) · node:test (built-in) | — | Supertest + test DB | Playwright request |
| Python (FastAPI) | pytest | — | httpx + TestClient | Playwright request |
Frontend vs backend test commands
# Angular
ng test # Jasmine + TestBed (Karma, or experimental Vitest)
pnpm test:e2e # Playwright
# React (Vite / Next.js)
pnpm test # Vitest + Testing Library
pnpm test:e2e # Playwright
# Node.js backend
pnpm test # Vitest + Supertest (API integration)
# Python (FastAPI) backend
uv run pytest # unit + TestClient integrationWhat Playwright covers
Playwright runs real browser tests against deployed applications:
- User flows (login, checkout, dashboard navigation)
- Cross-browser checks (Chromium, Firefox, WebKit)
- Visual regression (optional, via screenshots)
- API testing via the
requestfixture (no browser needed)
Playwright does not replace unit tests. Use it for critical user journeys that span multiple pages and services.
Required checks before merge
PR merge gate (alpha / beta / prod)
pnpm lint— no lint errors.pnpm typecheck— no type errors.pnpm test— unit + integration pass (the enforced gate).- Playwright smoke suite passes against the Alpha preview URL.
For release PRs to
prod: latest nightly load run is green (see Performance & Load).
How leading realtime/software teams test
Our flow follows the patterns used by high-scale realtime product teams (collaboration, chat, streaming). The principles below are what we aim for:
| Principle | What it means for us |
|---|---|
| Shift left | Cheapest tests (unit/integration) run first, on every PR, before any deploy |
| Ephemeral preview per PR | Every PR gets an Alpha preview URL that E2E runs against — no shared "dev breaks everyone" env |
| Trunk-based + fast CI | Small PRs, fast gates; keep the merge queue green |
| Test the realtime path | WebSocket/Socket.io flows get dedicated E2E + load tests (presence, reconnection, fan-out) |
| Load test before launch | Big launches run k6 load + soak against Beta with explicit SLO thresholds |
| Progressive delivery | Promote to Prod behind feature flags / canary; watch metrics before full rollout |
| Synthetic monitoring | Prod is continuously probed by scripted checks; alerts page on-call |
| Flaky = broken | A flaky test is treated as a failing test and fixed, never retried away |
Documentation flow
| Guide | When to read |
|---|---|
| Playwright Setup | First time setting up E2E locally |
| Writing E2E Tests | Adding or updating test cases |
| CI Integration | Wiring Playwright into GitHub Actions |
| Performance & Load Testing | Load, stress, soak, and realtime perf |
Official documentation
- Playwright Documentation
- Vitest — unit and integration tests
- Testing Library — component tests
- pytest — Python unit + integration
- k6 — load and performance testing