Payroll Testing
Payroll regulations encode complex business rules — tax tables, thresholds, retroactive calculations, edge cases. Without automated tests, every change to a regulation carries the risk of breaking existing behaviour silently.
The Payroll Engine provides a built-in test framework that covers the full payroll lifecycle: from case data entry and validation through payrun calculation to report output. Tests are defined as JSON files alongside the regulation, executed via the Payroll Console, and can be integrated into any CI/CD pipeline.
This approach is the basis for Test-Driven Payroll Development — writing tests before implementing regulation logic, using them as a living specification, and running them continuously to catch regressions early.
Contents
| Section | Description |
|---|---|
| Test Methods | Overview of all test methods with console commands |
| Case Testing | Validate and build test with .ct.json |
| Payrun Testing | Tenant, employee and preview test variants |
| Load Testing | Generate, setup, execute — CSV timing report |
| Report Testing | Build and execution tests for reports |
Test Methods
| Test Method | Test Scope | Payroll Console | JSON Extension |
|---|---|---|---|
| Case Available Test | Test for case availability | CaseTest |
.ct.json |
| Case Build Test | Test for case build | CaseTest |
.ct.json |
| Case Validate Test | Test for validating the case | CaseTest |
.ct.json |
| Payrun Test | Test the company payroll run | PayrunTest |
.pt.json |
| Payrun Employee Test | Test the employee payroll run | PayrunEmployeeTest |
.et.json |
| Payrun Employee Preview Test | Test payroll via preview (no persistence) | PayrunEmployeePreviewTest |
.et.json |
| Report Build Test | Test the report build | ReportTest |
.rt.json |
| Report Execute Test | Test the report execution | ReportTest |
.rt.json |
Case Testing
The following case test shows the validation of the salary lower limit from the start example.
Example Case Validation Test Test.Salary.ct.json:
# yaml-language-server: $schema=PayrollEngine.CaseTest.schema.json
testName: Test.Salary
tenantIdentifier: StartTenant
userIdentifier: lucy.smith@foo.com
employeeIdentifier: mario.nuñez@foo.com
payrollName: StartPayroll
validateTests:
- testName: Employee.Salary.499.Test # below minimum — expects rejection
input:
userIdentifier: lucy.smith@foo.com
employeeIdentifier: mario.nuñez@foo.com
divisionName: StartDivision
case:
caseName: Salary
values:
- caseFieldName: Salary
value: "499" # below minimum (500) → invalid
start: 2023-02-01T00:00:00.0Z
created: 2023-02-15T18:22:45.0Z
output:
issues:
- caseFieldName: Salary
issueType: CaseInvalid # validation action rejects the value
number: 400 # HTTP 400 Bad Request
- testName: Employee.Salary.500.Test # at minimum — expects acceptance
input:
userIdentifier: lucy.smith@foo.com
employeeIdentifier: mario.nuñez@foo.com
divisionName: StartDivision
case:
caseName: Salary
values:
- caseFieldName: Salary
value: "500" # at minimum (500) → valid
start: 2023-02-01T00:00:00.0Z
created: 2023-02-15T18:22:45.0Z
output:
values:
- caseFieldName: Salary
value: "500" # value accepted unchanged
The command PayrollConsole CaseTest Test.Salary.ct.json runs the case test.
See also example Case Test.
Payrun Testing
The payrun test is available in three variants:
- Tenant payrun test — tenant exists only during the test
- Employee payrun test — the test is performed on the copy of an employee
- Employee preview test — the test uses the preview API without persisting results
Testing the payrun is described in the Basic payroll example and Advanced payroll example.
Employee Preview Test
The PayrunEmployeePreviewTest command runs payrun invocations through the preview API and compares the in-memory results against expected values. Because preview does not persist results, no employee duplication or cleanup is needed, making tests faster and side-effect-free.
Preview tests use the same .et.json format as employee tests. The engine accepts any RetroPayMode to match production behavior. If retroactive calculation is triggered during a preview invocation, the endpoint returns HTTP 422. Wage type expressions that depend on historical results from prior periods will not find results from earlier preview invocations.
PayrunEmployeePreviewTest Test.et.json
PayrunEmployeePreviewTest *.et.json /showall /TestPrecision3
See Payrun Job Preview for business scenarios, restrictions, and a detailed example.
See also the Payrun tests.
Load Testing
The Payroll Console includes built-in commands for payrun performance testing. A load test follows four steps:
- Generate —
LoadTestGeneratecreates a scaled exchange file from any regulation template, producing a configurable number of employees with case changes. - Setup —
LoadTestSetupbulk-imports the generated employees via the bulk creation API for fast setup. - Setup Cases —
LoadTestSetupCasesbulk-imports case changes viaAddCasesBulkAsync, replacing the slower standardPayrollImportfor load test scenarios. - Execute —
PayrunLoadTestruns the payrun with a configurable number of warmup iterations and measured repetitions, producing a CSV report with client and server timing.
LoadTestGenerate Template.json /employees:1000 /output:LoadTest.json
LoadTestSetup LoadTest.json
LoadTestSetupCases LoadTest.json
PayrunLoadTest LoadTest.json /warmup:2 /repetitions:5
The CSV report includes per-iteration timings for both client round-trip and server-side processing, which can be used to identify performance bottlenecks and regression over time.
Load testing works best with parallel employee processing enabled to measure realistic throughput.
Report Testing
In payroll reports, both report creation (report parameters) and report execution can be tested. The report tests can be defined by configuration (JSON) or by programming (C# with Client Services).
See also the Report Test
See Also
- Automation — scripting for cases, payruns and reports
- Regulations
- Tests with test examples