Skip to main content

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.

SuiteWhereRunnerMeasured 2026-08Guide
Backend unitbackend/src/test/java/com/motorph/payroll/JUnit via mvn test51 classes / 423 tests, all greenbackend-tests.md
Frontend unitfrontend/src/**Vitest via npm test4 files / 60 tests, all greenfrontend-tests.md
End-to-ende2e/Playwright via npx playwright test36 spec files / 800 tests per browsere2e-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_dispatch only. 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-error while a backlog of pre-existing problems on code that predates the gate is worked down. The workflow comment states the exit condition: drop continue-on-error and add --max-warnings 0 the day it reaches zero.
  • The four *IT tenancy tests. This one is easy to miss. TenantIsolationIT, RowLevelSecurityIT, TenantProvisioningIT and RecognitionTenantIsolationIT — 35 tests — match none of Surefire's default include patterns, and no Failsafe plugin is bound to the build. mvn test, mvn verify and 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.