Skip to content

Regression test plan for a payments release: the template we use

A regression test plan for a payments release selects tests by the money flows a change touches, runs them in risk tiers, and ends with a ledger reconciliation of the test run. Our template records scope, suites per tier, entry and exit criteria, environment, synthetic data, the reconciliation check, and the named roles who sign the release.

Adrian Voss, Lead QA engineer, payments and acquiringPublished Updated

Where the template comes from: ISO/IEC/IEEE 29119-3:2021

The reference for test documentation is ISO/IEC/IEEE 29119-3:2021, Part 3: Test documentation, second edition, published on 28 October 2021 per the IEC Webstore. The IEEE SA page lists it as an Active Standard when we read it on 22 September 2026. The public preview gives clause 7.2, Test plan, with these subclauses: context of testing, assumptions and constraints, stakeholders, testing communication, risk register, test strategy, testing activities and estimates, staffing, and schedule.

Three points from the preview shape how we use it:

  • Clause 4.1.1 says test documentation "shall be considered as conforming if it is available in an electronic format (e.g. records in a test management tool or spreadsheet), divided into separate documents, or combined with other documents into one document." A plan file in the repository next to the suites fits that wording.
  • Clause 4.1.3 says that for tailored conformance "the subset of test documentation for which tailored conformance is claimed, shall be recorded." The template below is a tailored subset, and we do not claim full conformance for it.
  • The introduction says users "can substitute the term 'product' for 'project', where appropriate", which suits product teams that release every week.

The standard defines the headings. The money-flow tiers, the reconciliation gate, and the sign-off roles below are our practice, and no clause of 29119-3 requires them.

Why a payments regression plan needs a money-flow structure

A regression plan organised by screens or features passes a release whose defect sits in the ledger. Three failure patterns show the gap:

  • Rounding change in a fee calculation. Unit tests pass, the screen shows the expected fee, and every transaction leaves a residue of one minor unit in a suspense account until month-end close finds the drift.
  • Retry after a processor timeout. A client library upgrade drops the idempotency key on retry, and a customer is charged twice for one purchase. The payment idempotency guide shows the test for it.
  • Settlement parser change. A new file version books a partial refund on the next business day, and payouts calculated that morning use the wrong available balance.

Each of these passes a feature-level regression run. Each fails a plan that scopes by money flow and ends with a reconciliation of what the run posted.

The regression test plan template

This is the template we use on payments and fintech releases. It is our practice. Copy the block into the repository and fill the brackets. Clause numbers in the headings map our sections to the 29119-3 headings they fill, so an auditor or partner bank reviewer can find each element.

MARKDOWN
# Regression test plan: [product] [version]
Plan ID: RTP-[version]   Status: draft | approved | closed
Conformance: tailored, ISO/IEC/IEEE 29119-3:2021 clause 7.2 subset
Release owner: [engineering lead]   Plan owner: [QA lead]

## 1. Scope (7.2.2 context, 7.2.6 risk register)
| Flow ID | Money-moving flow | Tier |
|---|---|---|
| F-01 | Authorisation, capture, refund | 1 |
| F-02 | Payout and bank transfer file | 1 |
| F-03 | Fee, interest, FX calculation | 1 |
| F-04 | Settlement and statement ingestion | 1 |
| F-05 | Limits, KYC and account status gates | 2 |
| F-06 | Statements and accounting exports | 2 |
| F-07 | Profile and content | 3 |

| Change ticket | Flows touched | Suites selected |
|---|---|---|
| [ticket] | [F-xx] | [suite IDs] |

Selection rules:
- Ledger, posting rules or shared libraries changed: all tier 1, plus reconciliation replay for ledger changes.
- Fee, interest, FX or rounding changed: calculation reference set plus tier 1 of that flow.
- Partner API or SDK changed: contract tests plus tier 1 of flows using that partner.
- UI only: tier 3, plus tier 1 journeys where the screen sets an amount.
- Out of scope: [flows], reason: [no code path change].

## 2. Suites by risk tier (7.2.7 test strategy)
| Tier | Suites | Pass rule |
|---|---|---|
| 1 | Ledger invariants, calculations, payment states, simulator failure paths, idempotent retry | All pass; no automatic retry of a failed money assertion |
| 2 | Gating, statements, exports | Pass, or waiver by product owner |
| 3 | UI journeys | Open defects listed |

## 3. Entry criteria
- [ ] Build [ID] and commit [hash] frozen; every ticket mapped to flow IDs
- [ ] Environment matches manifest [file], simulator versions included
- [ ] Synthetic data seeded for run [run ID]; balances captured; clock and FX table [version] set

## 4. Environment and synthetic data (7.2.7)
- Isolated ledger database per run; processor and bank simulators [versions]
- Synthetic accounts; processor test card numbers only; no production cardholder or account data
- Edges: one minor unit, zero- and three-decimal currencies, cut-off, month end, leap day

## 5. Exit criteria
- [ ] Tier 1 passed on the frozen build; tier 2 passed or waived with owner
- [ ] Every open defect has a financial impact field filled
- [ ] Section 6 queries returned zero rows; evidence stored with build and run ID

## 6. Reconciliation check
Run reconcile.sql with run_id = [run ID]. Any returned row is a tier 1 failure.

## 7. Sign-off (7.2.4 stakeholders)
| Role | Signs for | Name, date |
|---|---|---|
| QA lead | Exit criteria met | |
| Engineering lead | Release decision, residual defects | |
| Finance operations | Reconciliation output | |
| Product owner | Tier 2 and 3 waivers | |
| Compliance | Changes to mapped regulatory requirements | |

## 8. Completion (feeds 7.4 test completion report)
Deviations: [list]   Residual risks: [list]

In our practice, a change ticket in section 1 that names no flow ID goes back to its author before the run starts, because an unmapped change selects no suite. Where a change touches a regulatory requirement, the compliance row uses the same trace as our sample requirement traceability matrix, which links each requirement to test case IDs and the last result.

The reconciliation queries behind section 6

Test data in section 4 excludes production cardholder and account data, so these queries read only the run's synthetic ledger. They assume PostgreSQL, signed amounts in minor units (debit positive, credit negative), balances stored with the same sign, and a table the processor simulator writes for each settled transaction.

SQL
-- Schema the queries expect
CREATE TABLE ledger_entries (run_id text, txn_ref text, account_id text, currency char(3), amount_minor bigint, entry_type text);
CREATE TABLE balances_before (run_id text, account_id text, currency char(3), balance_minor bigint);
CREATE TABLE balances_after  (run_id text, account_id text, currency char(3), balance_minor bigint);
CREATE TABLE sim_settlement  (run_id text, txn_ref text, currency char(3), amount_minor bigint);

-- Q1: every transaction nets to zero per currency
SELECT txn_ref, currency, SUM(amount_minor) AS net_minor
FROM ledger_entries
WHERE run_id = :'run_id'
GROUP BY txn_ref, currency
HAVING SUM(amount_minor) <> 0;

-- Q2: each balance moved by exactly the sum of its entries
SELECT a.account_id, a.currency,
       a.balance_minor - b.balance_minor AS moved_minor,
       COALESCE(SUM(e.amount_minor), 0) AS posted_minor
FROM balances_after a
JOIN balances_before b
  ON b.run_id = a.run_id AND b.account_id = a.account_id AND b.currency = a.currency
LEFT JOIN ledger_entries e
  ON e.run_id = a.run_id AND e.account_id = a.account_id AND e.currency = a.currency
WHERE a.run_id = :'run_id'
GROUP BY a.account_id, a.currency, a.balance_minor, b.balance_minor
HAVING a.balance_minor - b.balance_minor <> COALESCE(SUM(e.amount_minor), 0);

-- Q3: simulator settlement matches what the receivable says is due, and the receivable clears
WITH s AS (
  SELECT txn_ref, currency, SUM(amount_minor) AS settled_minor
  FROM sim_settlement WHERE run_id = :'run_id' GROUP BY txn_ref, currency
), l AS (
  SELECT txn_ref, currency,
         SUM(amount_minor) FILTER (WHERE entry_type <> 'settlement') AS due_minor,
         SUM(amount_minor) AS net_minor
  FROM ledger_entries
  WHERE run_id = :'run_id' AND account_id = 'processor_receivable'
  GROUP BY txn_ref, currency
)
SELECT COALESCE(s.txn_ref, l.txn_ref) AS txn_ref,
       COALESCE(s.currency, l.currency) AS currency,
       s.settled_minor, l.due_minor, l.net_minor
FROM s FULL OUTER JOIN l ON l.txn_ref = s.txn_ref AND l.currency = s.currency
WHERE s.settled_minor IS DISTINCT FROM l.due_minor
   OR l.net_minor <> 0;

Run the file with psql -v run_id=RUN-2026-07-28-01 -f reconcile.sql. Q3 needs one more assumption: sim_settlement holds the net amount the processor settles per transaction, positive when it pays the merchant. Captures debit processor_receivable, refunds credit it, and the ingested settlement posts with entry_type = 'settlement'. A transaction captured and never settled, settled for a different amount, or booked from the settlement file twice returns a row. The ledger reconciliation testing guide covers matching against real bank statement and processor file formats, which this post-run check leaves out.

Where the plan sits in a delivery pipeline

The plan decides what runs and who signs. The suites, their CI stages, and the release gates that execute it are the scope of test automation. If the release has no agreed risk ranking of money flows yet, the tier table in section 2 comes out of a QA audit and test strategy, and the plan is filled from that strategy release by release.

Scope your testing

Send FintechAssuranceLabs your product, segment, money flows, and the standards that need evidence, and get a proposed test scope with its deliverables.

Scope your testing