Testing
Three suites, three runners, three very different kinds of confidence. This page is the map: what each suite is for, which gates a change actually has to pass, and which checks exist but are not enforced.
| Suite | Where | Runner | Measured 2026-08 | Guide |
|---|---|---|---|---|
| Backend unit | backend/src/test/java/com/motorph/payroll/ | JUnit via mvn test | 51 classes / 423 tests, all green | backend-tests.md |
| Frontend unit | frontend/src/** | Vitest via npm test | 4 files / 60 tests, all green | frontend-tests.md |
| End-to-end | e2e/ | Playwright via npx playwright test | 36 spec files / 800 tests per browser | e2e-playwright.md |
Counts drift. Regenerate them rather than trusting them — the last line of
mvn test, of npm test, and of npx playwright test --list are the
authoritative numbers.
The three suites in one paragraph each
Backend — cd backend && mvn test. JUnit 5 with Mockito. With one exception
noted below, no test starts Spring and none needs a database: every collaborator
is mocked, so the suite finishes in under a minute. That speed is bought by
giving up two things you might assume are covered — repository @Query
behaviour and @PreAuthorize enforcement are never tested, because both are
mocked or bypassed. Run it from backend/; mvn test at the repo root runs
nothing and still prints BUILD SUCCESS, because the root pom.xml is the dead
JavaFX project. The exception: two tenancy classes start a real Postgres through
Testcontainers, so mvn test now needs a working Docker daemon. Details,
filtering and the gaps: backend-tests.md.
Frontend — cd frontend && npm test. Vitest in a node environment, with
no jsdom and no @testing-library, so nothing renders a component. Four files
cover the modules whose failures would be silent rather than loud: the AG Grid
filter-model translation, the one-shot grid-state migration, the payslip
template registry, and the SEO route table's agreement with sitemap.xml.
Coverage is thin and deliberately so — everything else is exercised through the
browser suite. Details: frontend-tests.md.
E2E — npx playwright test from the repo root. The only suite that sees real
SQL, real permissions and a real browser. It requires the Docker stack running
(frontend :5173, backend :8081, Postgres :5434) and ALTCHA_ENABLED=false,
since the helpers log in by posting to /api/auth/login directly and a CAPTCHA
challenge would answer 428. Specs assume the seeded demo data and the demo
personas, and most suites run serially because they mutate live data — so don't
point two Playwright runs at the same stack, they share one database and will
race. Details: e2e-playwright.md and the colocated
e2e/README.md.
What is actually enforced
Green checks are only worth what they block. The honest split:
Gates — these fail a pull request and stop a deploy. Backend mvn test,
frontend tsc -b type-check, and frontend Vitest all run on every PR via
tests.yml, and deploy.yml calls that
same workflow as its first job — so a red suite stops the pipeline before an
image is built. Alongside them, an e2e smoke spec runs against a freshly
built and seeded stack, plus CodeQL and gitleaks.
Not gates — these run, or exist, but block nothing:
- The full Playwright suite. Manual
workflow_dispatchonly. It has documented known-failing specs, so making it a merge gate would block every merge on failures nobody introduced. Run it locally before pushing anything broad. - ESLint. Runs with
continue-on-errorwhile a backlog of pre-existing problems on code that predates the gate is worked down. The workflow comment states the exit condition: dropcontinue-on-errorand add--max-warnings 0the day it reaches zero. - The four
*ITtenancy tests. This one is easy to miss.TenantIsolationIT,RowLevelSecurityIT,TenantProvisioningITandRecognitionTenantIsolationIT— 35 tests — match none of Surefire's default include patterns, and no Failsafe plugin is bound to the build.mvn test,mvn verifyand CI all skip them. They pass when invoked by name (mvn test -Dtest='*IT'), and that is the only way they ever run. Do it before merging anything touching tenancy, entities or migrations.
The workflow-by-workflow breakdown is in ci-quality-gates.md, with the deployment side in ../deployment/ci.md.
Before you push
cd backend && mvn test # 423 tests
cd frontend && npm run type-check && npm test
That is the CI gate reproduced locally, and it is fast enough to run every time.
Add npm run lint if you touched the frontend, since CI will not fail on it for
you. If your change touched tenancy, add mvn test -Dtest='*IT'. If it touched a
grid, a form or a workflow a user walks through, run the relevant Playwright spec
against a local stack — the unit suites cannot see any of it.
Related
backend/src/test/README.md— the colocated backend runbook, with copyable templates for both test styles.e2e/README.md— Playwright conventions, the per-worker login cache, grid helpers and fixture disambiguation.- recruitment-qa-test-plan.md — the manual QA plan for the recruitment module.
- ../coding-standards.md — conventions a reviewer will expect, tests included.