Happy-path tests are comfortable and nearly useless for payments. The failures that hurt are partial: money left one ledger but not the other, a timeout that hid a success, a reversal that arrived twice. Testing for these states is not pessimism; it is the only way to know how a system behaves when it matters.

The scenarios worth writing first

Some failure modes recur across every payment system. Build them into the test suite deliberately rather than waiting for production to find them.

  • partial settlement — one leg completes, the other does not
  • timeouts after execution — the operation succeeded but the caller never learned
  • duplicate instructions — the same intent submitted twice
  • reversals and compensating entries — undoing without erasing
  • webhook loss and reordering — events missing or arriving out of sequence

Each scenario should have a defined expected outcome — not just “does not crash”, but the exact state of balances, statuses and records afterwards.

Inject failure, do not imagine it

Failure injection means causing these conditions on purpose in a controlled perimeter. Because SUPA today runs business units on licensed partners' rails within a virtual special economic zone, a team can exercise real flows — accounts, FX, payouts — while remaining isolated from live consequences. The agent unit cost of $99 per year makes a thorough suite affordable to maintain.

Assert on invariants

Tests should assert on properties that must always hold, not only on expected values. Debits equal credits. A reversal returns balances to their prior state. A duplicate instruction produces one operation. Every entry is attributed to a principal, an agent and a policy version. Invariants catch the cases you did not enumerate. A practical layout is to run the suite against a controlled perimeter, promote each scenario from an integration test to a regression test once it passes, and keep the failure fixtures in the repository beside the code that must survive them.

In short

  • Test partial settlement, timeouts, duplicates and reversals first.
  • Inject failures deliberately, in a controlled perimeter.
  • Assert on invariants — matching entries, single execution, attribution.
  • Treat reconciliation as part of the test, not only operations.

This is general information, not legal, tax or financial advice. Build and test your first flow: developers.