Skip to content

Testing

The ERPNext Incentive Compensation Engine uses multiple layers of testing to verify commission calculations, configuration resolution, historical ledger behavior, workflows, reports, and the integration with ERPNext Sales Invoices.

The testing approach separates low-level calculation tests from higher-level integration and end-to-end tests.

Testing Strategy

The main testing layers are:

Unit Tests
    ↓
Integration Tests
    ↓
End-to-End Tests

Each layer answers a different question.

Test Layer Main Question
Unit Does an individual calculation or function behave correctly?
Integration Do multiple application components work together correctly?
End-to-End Does the complete commission lifecycle work from source transaction to payout?

Test Structure

Application tests are located under the application's test directories.

The tests cover areas such as:

  • commission calculations
  • rule resolution
  • commission ledger behavior
  • statements
  • payouts
  • reports
  • end-to-end commission workflows

When adding a new feature, tests should be added at the lowest appropriate layer first and then expanded to integration or end-to-end coverage when the feature crosses component boundaries.

Running the Test Suite

From the Frappe Bench directory, the application test suite can be run with:

bench --site <your-site> run-tests --app incentive_compensation

For example:

bench --site acme-electronics.localhost run-tests --app incentive_compensation

The command asks Frappe to discover and run the tests belonging to the application.

Test Environment

Tests should run against a Frappe site with the application installed.

A dedicated development or test site is preferable to a production site.

For example:

incentive-test.localhost

A clean or isolated site is especially useful for integration and end-to-end testing because ERPNext data and configuration can affect test behavior.

Unit Testing

Unit tests verify focused pieces of business logic without requiring the entire commission lifecycle.

The calculation layer is particularly suitable for unit testing because its functions can operate on explicit inputs and return calculated values.

Calculation Tests

Calculation tests should cover:

  • percentage commissions
  • fixed commissions
  • tiered commissions
  • tier boundaries
  • open-ended final tiers
  • decimal arithmetic
  • Sales Team allocation

A simple percentage calculation can be tested with:

Base Amount = ₹10,000
Rate = 5%

Expected Commission = ₹500

The test should verify the calculated value directly.

Percentage Tests

A percentage test should verify the basic formula:

Commission = Base Amount × Rate / 100

Example:

Base Amount = ₹20,000
Rate = 10%

Expected = ₹2,000

Boundary and decimal values should also be tested where appropriate.

Fixed Amount Tests

A fixed amount test verifies that the configured fixed commission is returned correctly.

Example:

Fixed Amount = ₹500

Expected Commission = ₹500

The test should also verify that unrelated transaction amount changes do not incorrectly turn the fixed calculation into a percentage calculation.

Tiered Commission Tests

Tiered calculations require more boundary coverage.

Tests should verify:

  • values inside a tier
  • values at the lower boundary
  • values at the upper boundary
  • values between tiers
  • the final open-ended tier
  • multiple tier configurations

For example:

From       To         Rate
₹0         ₹10,000    2%
₹10,000    ₹20,000    3%
₹20,000    blank      5%

Tests should explicitly exercise the boundaries instead of testing only a value in the middle of a tier.

Sales Team Allocation Tests

Sales Team allocation should be tested independently of the final commission calculation.

Example:

Transaction Amount = ₹20,000

Sales Person A = 70%
Sales Person B = 30%

Expected bases:

A = ₹14,000
B = ₹6,000

This verifies that transaction preparation produces the correct inputs for subsequent commission calculation.

Resolver Tests

The resolver is responsible for finding applicable commission configuration.

Tests should cover:

  • active plans
  • inactive plans
  • plan validity dates
  • multiple applicable plans
  • newest applicable valid_from
  • rule matching
  • rule priority
  • enabled and disabled rules
  • tier resolution
  • payee resolution

Plan Selection

For multiple applicable plans, the test should verify that the plan with the most recent applicable valid_from is selected.

Conceptually:

Plan A → Valid From: January 1
Plan B → Valid From: April 1
Plan C → Valid From: July 1

Transaction Date: August 1

Expected Plan: Plan C

This is important because plan selection determines which rules are evaluated.

Rule Matching Tests

Rule matching should verify each supported condition.

Examples include:

Item
Item Group
Sales Person
Customer
Customer Group
Territory

Tests should include both matching and non-matching transactions.

A rule that does not match should not generate a commission.

Rule Priority Tests

When multiple rules can match, tests should verify that priority produces the intended result.

For example:

Rule A → Priority 1
Rule B → Priority 2

If both rules match, the rule with the lower priority number is evaluated first.

The test should verify that the expected rule is selected.

Ledger Tests

The Commission Ledger is the historical boundary of the calculation system.

Ledger tests should cover:

  • successful creation
  • required source information
  • source key generation
  • duplicate prevention
  • immutability
  • reversal creation
  • reversal references

Idempotency Test

A commission calculation should not create duplicate ledger entries when the same source calculation is processed again.

Conceptually:

First processing
    ↓
Ledger Entry Created

Second processing
    ↓
Existing Source Key
    ↓
No Duplicate Entry

The test should verify that only one historical commission entry exists for the same source calculation.

Ledger Immutability Tests

Historical ledger records should not be freely modified after creation.

Tests should verify that protected calculation fields cannot be changed after the entry exists.

The important principle is:

Calculated Result
       ↓
Ledger Entry
       ↓
Immutable History

This protects the audit trail.

Reversal Tests

When a source Sales Invoice is cancelled, the original commission entry should remain unchanged and a reversal entry should be created.

A reversal test should verify:

Original Commission
       ↓
Invoice Cancellation
       ↓
Reversal Entry

The reversal should:

  • represent the opposite financial effect
  • reference the original commission through reversal_of
  • use the appropriate reversal entry type

Statement Tests

Statement tests should cover both generation and workflow behavior.

Important areas include:

  • creating a Draft statement
  • finding eligible ledger entries
  • excluding entries already included in another non-cancelled statement
  • calculating gross commission
  • calculating adjustments
  • calculating net commission
  • creating the ledger-entry snapshot
  • setting the generation date
  • moving the statement through its workflow
  • protecting generated statement data

Statement Generation Test

A basic statement generation test can use:

Commission Ledger
₹500

Statement
Payee = Same Payee
Date Range = Includes Ledger Date

Expected:

Gross Commission = ₹500
Adjustments      = ₹0
Net Commission   = ₹500

The generated statement should contain the corresponding Commission Statement Entry.

Statement Eligibility Tests

Statement resolution should verify that ledger entries are selected only when they match:

  • Commission Payee
  • Company
  • Currency
  • date range
  • eligible ledger status

Ledger entries already included in another non-cancelled statement should be excluded.

Cancelled statements do not permanently consume the underlying ledger entries.

Statement Immutability Tests

Once a statement has been generated, its historical calculation data should be protected.

Tests should verify that users cannot freely change:

  • Commission Payee
  • Company
  • Currency
  • From Date
  • To Date
  • Gross Commission
  • Adjustments
  • Net Commission
  • Generation Date

The statement's ledger-entry snapshot should also be protected from ordinary modification.

Statement Workflow Tests

Statement workflow transitions should be explicitly tested.

The intended lifecycle is:

Draft
  ↓
Generated
  ↓
Under Review
  ↓
Approved
  ↓
Posted
  ↓
Paid

Generation is separate from the approval workflow.

The workflow should also allow the appropriate cancellation transitions.

Tests should verify that invalid direct transitions are rejected.

For example, a statement should not be able to jump directly from:

Generated
    ↓
Posted

without going through the required review and approval stages.

Payout Tests

Payout tests should cover:

  • creation from a Posted statement
  • payout amount
  • duplicate payout prevention
  • payout workflow
  • required payment information
  • marking a payout as Paid
  • updating the associated statement to Paid

The intended payout lifecycle is:

Pending
   ↓
Processing
   ↓
Paid

A payout can also move through the appropriate Failed and Cancelled states.

Payout Creation Test

A Posted statement with a positive net commission should produce a payout.

Example:

Statement Net Commission = ₹500

Expected Payout Amount = ₹500

The payout should reference the source statement and payee.

Payout Validation Tests

A payout should not be marked as Paid without the required payment information.

The payment process requires:

  • Payment Date
  • Payment Reference

Tests should verify each validation independently.

For example:

Missing Payment Date
        ↓
Reject Paid transition

and:

Missing Payment Reference
        ↓
Reject Paid transition

Payout and Statement Synchronization

When a payout is successfully marked as Paid, the associated Commission Statement should also become Paid.

This relationship should be covered by integration tests.

Expected behavior:

Payout
Processing
   ↓
Paid
   ↓
Statement becomes Paid

Report Tests

The application provides six reports:

  • Commission Summary
  • Commission by Payee
  • Commission by Plan
  • Commission by Rule
  • Commission by Invoice
  • Commission by Date

Report tests should verify that the correct Commission Ledger records are included and that filters produce the expected results.

Important filters include:

  • Company
  • From Date
  • To Date
  • Commission Payee
  • Commission Plan
  • Commission Rule
  • Sales Invoice

Commission by Date uses the date range to determine the reporting period.

Integration Testing

Integration tests verify that multiple application components work together.

Examples include:

Resolver
   ↓
Evaluator
   ↓
Calculator
   ↓
Ledger

and:

Statement
   ↓
Workflow
   ↓
Payout

Integration tests are particularly useful when a feature crosses module boundaries.

Sales Invoice Integration Test

A key integration test verifies that a submitted ERPNext Sales Invoice produces a commission ledger entry.

The expected flow is:

Create Sales Invoice
       ↓
Add Sales Team
       ↓
Submit
       ↓
Commission Processing
       ↓
Commission Ledger

The test should verify the resulting ledger information, including:

  • Sales Invoice
  • Commission Payee
  • Commission Plan
  • Commission Rule
  • Base Amount
  • Commission Amount
  • Transaction Date

Sales Invoice Cancellation Integration Test

The cancellation path should verify:

Submit Sales Invoice
       ↓
Commission Ledger Created
       ↓
Cancel Sales Invoice
       ↓
Reversal Ledger Created

The original ledger entry should remain intact.

End-to-End Testing

End-to-end testing verifies the complete commission lifecycle.

A complete scenario should cover:

Commission Configuration
        ↓
Sales Invoice
        ↓
Commission Ledger
        ↓
Commission Statement
        ↓
Review
        ↓
Approval
        ↓
Posting
        ↓
Commission Payout
        ↓
Payment

This verifies that the major application components work together as a real user workflow.

Example End-to-End Scenario

A representative test can use:

Company: Incentive Test Company
Plan: Standard Sales Commission
Rule: Demo Item Commission
Payee: Test Salesperson
Item: Test Item
Sales Invoice Amount: ₹10,000
Rate: 5%

Expected commission:

₹10,000 × 5%
= ₹500

The test then verifies:

Sales Invoice
      ↓
Ledger = ₹500
      ↓
Statement = ₹500
      ↓
Statement Posted
      ↓
Payout = ₹500
      ↓
Payout Paid
      ↓
Statement Paid

Testing the Workspace and UI

The most important business logic should be tested at the Python/application level rather than relying only on browser interaction.

UI testing is still useful for verifying the user workflow.

Important UI scenarios include:

  • creating plans
  • creating rules
  • creating payees
  • generating statements
  • moving statements through workflow
  • creating payouts
  • entering payment information
  • marking payouts as Paid
  • viewing reports

For example, the payout UI should prevent a user from marking a payout as Paid until Payment Date and Payment Reference have been supplied.

Regression Testing

After changing calculation or workflow logic, run the relevant tests and then run the broader application test suite.

A typical progression is:

Change Code
   ↓
Run Focused Tests
   ↓
Fix Failures
   ↓
Run Integration Tests
   ↓
Run Full Application Tests

Focused tests make development faster, while the full suite helps detect regressions elsewhere in the application.

Test Data

Tests should use clearly identifiable test records.

Names such as:

Test Salesperson
Test Item
Test Commission Plan
Test Commission Rule

make test failures easier to understand.

For integration and end-to-end testing, an isolated test site is preferable so that unrelated ERPNext records do not interfere with the scenario.

Known Test Environment Consideration

ERPNext test helpers can create or depend on accounting configuration such as Fiscal Years.

When running application tests on an existing development site, unrelated site data can sometimes interfere with ERPNext helper functions.

For example, an existing overlapping Fiscal Year can cause an ERPNext test fixture to fail before the application's own test logic is reached.

When a failure occurs during test discovery or setup, first determine whether the failure comes from:

Application Code
       or
Test Environment / ERPNext Fixture Setup

A clean or dedicated test site is useful when diagnosing this type of failure.

Test Failure Investigation

When a test fails, identify the layer first.

Calculation failure
    ↓
Check calculator / engine

Resolution failure
    ↓
Check resolver / evaluator

Ledger failure
    ↓
Check ledger / source key / immutability

Statement failure
    ↓
Check statement resolver / statement / workflow

Payout failure
    ↓
Check payout / payout workflow

Event failure
    ↓
Check hooks / commission events

Report failure
    ↓
Check report query / filters

This keeps debugging focused.

What Should Be Tested Before a Release

Before releasing a new version, verify at minimum:

Calculation

  • percentage
  • fixed amount
  • tiered
  • Sales Team allocation
  • decimal values

Configuration

  • plan selection
  • plan validity
  • rule matching
  • rule priority
  • payee resolution

Ledger

  • creation
  • idempotency
  • immutability
  • reversal

Statements

  • generation
  • eligible ledger selection
  • duplicate consumption prevention
  • totals
  • immutability
  • workflow

Payouts

  • creation
  • duplicate prevention
  • workflow
  • payment validation
  • statement synchronization

Events

  • Sales Invoice submission
  • Sales Invoice cancellation

Reports

  • all six reports
  • required filters
  • date filtering
  • expected aggregation

End-to-End

  • complete commission lifecycle from Sales Invoice to Paid payout

Development Testing Workflow

A practical development workflow is:

1. Make a focused change
        ↓
2. Run the relevant unit tests
        ↓
3. Run related integration tests
        ↓
4. Perform an end-to-end check if the change affects a workflow
        ↓
5. Run the full application test suite
        ↓
6. Review the diff
        ↓
7. Commit the change

This reduces the time spent diagnosing unrelated failures.

Test Philosophy

The test suite should protect the application's most important business guarantees:

Correctness

The commission amount must be calculated correctly.

Determinism

The same transaction and configuration should produce the same result.

Idempotency

Repeated processing should not create duplicate commissions.

Historical Integrity

Historical commission calculations must remain stable.

Workflow Integrity

Statements and payouts must follow their intended lifecycle.

Traceability

A commission should be traceable from the ledger back to its source transaction and configuration.

Reversibility

Cancelled source transactions should produce auditable reversal entries rather than destroying history.

Next Step

Continue with Contributing to learn how to set up the development environment, make changes, run checks, and contribute changes to the project.