Skip to content

Payroll Testing

Regulator|Scripting API · C# 14

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

Payroll Testing

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:

  1. GenerateLoadTestGenerate creates a scaled exchange file from any regulation template, producing a configurable number of employees with case changes.
  2. SetupLoadTestSetup bulk-imports the generated employees via the bulk creation API for fast setup.
  3. Setup CasesLoadTestSetupCases bulk-imports case changes via AddCasesBulkAsync, replacing the slower standard PayrollImport for load test scenarios.
  4. ExecutePayrunLoadTest runs 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