Skip to content

Testing

Prescriptive testing policy for SectorWars 2102. This document describes how testing should work across the source repos. Coverage gaps for specific features are tracked inline in FEATURES/ using the 🚧 Partial or 🐛 Bug markers — not here.


Test landscape

Tests live alongside the code they cover, in the source repos:

Surface Location
Gameserver (Python) Sectorwars2102/services/gameserver/tests/
Admin UI (TypeScript / React) Sectorwars2102/services/admin-ui/ (colocated with components)
Player client (TypeScript / React) Sectorwars2102/services/player-client/ (colocated with components)
End-to-end Sectorwars2102/e2e_tests/
World / sector generator sw2102-bang/ (colocated; mirror gameserver conventions)

sw2102-docs itself does not host tests; documentation lints (link-checking, formatting) belong in this repo's CI as defined under "CI" below.


How to run tests

Gameserver

From Sectorwars2102/services/gameserver/:

  • Full suite: pytest
  • One file: pytest tests/test_<module>.py
  • One test: pytest tests/test_<module>.py::test_<name>
  • With coverage: pytest --cov=src --cov-report=term-missing

Admin UI

From Sectorwars2102/services/admin-ui/:

  • Full suite: npm test
  • Watch mode: npm test -- --watch
  • One file: npm test -- <path-or-pattern>

Player client

From Sectorwars2102/services/player-client/:

  • Full suite: npm test
  • Watch mode: npm test -- --watch
  • One file: npm test -- <path-or-pattern>

End-to-end

From Sectorwars2102/e2e_tests/:

  • Full suite: npx playwright test
  • One spec: npx playwright test foundation-sprint/<spec>.spec.ts
  • Headed (debugging): npx playwright test --headed
  • UI mode: npx playwright test --ui

E2E tests assume the full local stack (gameserver, admin-ui, player-client, database, redis) is running. See ARCHITECTURE/ for the dev-environment bring-up.


What we test at each layer

The target test pyramid:

Unit tests

  • Where: colocated with the code they cover, in each service.
  • What: pure functions, service classes with mocked dependencies, individual React components, schema validators.
  • Speed target: the full unit suite for any one service runs in under a minute.
  • Required for: every public function in a service module; every component with conditional rendering or input handling; every model validator.

Integration tests

  • Where: services/gameserver/tests/integration/ for backend, e2e_tests/ for cross-service.
  • What: API endpoint behaviour against a real database; WebSocket flows against a real Redis; cross-service contracts (e.g. gameserver ↔ admin-ui auth).
  • Required for: every REST and WebSocket endpoint exposed by the gameserver; every multi-step workflow that touches more than one service.

End-to-end tests

  • Where: Sectorwars2102/e2e_tests/.
  • What: player-visible flows running through the player client and admin UI against the real stack. Examples: first login flow, trade-loop happy path, combat resolution, multi-channel chat, sector transition.
  • Required for: every flow described in a FEATURES/ doc as user-facing.

A feature is not considered ✅ Shipped in FEATURES/ until it has at least one e2e test or documented manual test plan covering its happy path.


How to add a new test

Gameserver

  1. Add a file under Sectorwars2102/services/gameserver/tests/ named test_<module>.py matching the module under test.
  2. Use pytest style (functions, not classes) unless the test needs shared setup.
  3. Use the existing fixtures in tests/conftest.py for database and authentication.
  4. For DB-backed tests, mark with @pytest.mark.integration if the test requires a live database; leave unmarked for pure unit tests.
  5. Run pytest tests/test_<module>.py locally before committing.

Admin UI / Player client

  1. Add a <Component>.test.tsx file next to <Component>.tsx.
  2. Use the project's existing test renderer wrapper (provides router, query client, theme).
  3. Prefer testing user-visible behaviour (queries by role, label, text) over implementation details.
  4. Mock network calls at the fetch boundary, not at the component boundary.
  5. Run npm test -- <ComponentName> locally before committing.

End-to-end

  1. Add a .spec.ts under the appropriate subdirectory of e2e_tests/ (e.g. foundation-sprint/, multi-regional/).
  2. Use the existing page-object helpers; do not select by raw CSS unless no role/label exists.
  3. Each spec should be independently runnable — set up its own seed data, clean up after itself.
  4. Run npx playwright test <spec> locally with the full stack up before committing.

CI

Continuous integration runs on every PR and on every merge to the main branch. The target pipeline lives at .github/workflows/ in the source repos.

Per-PR jobs:

  • Lint — language-appropriate linters for each service.
  • Unit tests — full unit suite for each service, run in parallel.
  • Integration tests — gameserver integration suite against a CI-provisioned Postgres and Redis.
  • E2E tests — Playwright suite against a CI-provisioned full stack.
  • Doc checks — for sw2102-docs, link validation and conventions checks per CONTRIBUTING.md.

Per-merge jobs additionally:

  • Build container images for each service.
  • Run smoke tests against the resulting images.

A PR is not mergeable until every required check passes. Flaky tests are not retried at the CI level — fix them or quarantine them with an explicit 🐛 Bug entry in the relevant FEATURES/ doc.


Coverage and quality

Target coverage is meaningful coverage, not a percentage. Each test should:

  • Have a clear name describing the behaviour under test.
  • Fail for one specific reason.
  • Either run fast (unit) or test something a fast test cannot (integration, e2e).

When a feature is added, the corresponding FEATURES/ doc and at least one test are part of the same PR. If you find a coverage gap on an existing feature, mark the feature 🚧 Partial and link to the gap in the feature doc — do not silently add a TODO here.