Take $49.995 as an example. This amount can be part of a discount, tax, or interest calculation. Round it at the wrong point, and the resulting payment is off by a cent every time that code runs.
Only after the fact does a reconciliation report usually pick it up. Tracing it back to the specific rounding function responsible takes real digging.
A transaction can post successfully and still carry the wrong number. The screen shows one figure while the ledger, the API response, or the bank statement shows another, creating a problem software testing in financial services has to catch.
Testing for it means checking the number itself, not just whether the flow completed, starting with how each system represents money: major units and minor units.
Payment platform testing needs to account for rules and scenarios such as:
These specifics come from card scheme and payment provider documentation.
PSD2 requires an extra verification step, known as strong customer authentication, for any transaction above a set amount. If a QA suite’s test data stays below that amount, a checkout-flow test suite can pass in full without that verification step.
PSD3 will layer new authentication and fraud-prevention rules on top of PSD2’s, with most compliance deadlines falling in 2027 and 2028. In either regime, authentication logic only gets verified if test data actually triggers it.
A similar blind spot can show up in the ledger, just with different stakes. A missed authentication check is a compliance problem. A race condition in a ledger update is a financial discrepancy, which in worst cases requires reporting it to regulators.
When there is a clear error, like a transaction failing, someone notices right away. It is not the same to have a wrong number with no visible error. Nothing marks the exchange as suspicious, so it can stay in production for months.
Tricentis’ 2025 Quality Transformation Report found that 40% of organizations worldwide put the annual cost of poor software quality at $1 million or more. Financial services reported the steepest losses of any industry surveyed: 45% said the figure runs above $5 million a year. Payment platforms sit inside that industry category, exposed to the same cost pressure the survey describes.
The major unit is a currency’s main unit, the whole-number amount most people think of as ‘money.’ The minor unit is the smallest fraction of that currency a system represents, and it varies by currency. ISO 4217, the international standard that assigns every currency its three-letter code, defines how many decimal places, or minor units, each one uses:
| Currency | Major unit | Minor unit | Decimal places | Example |
|---|---|---|---|---|
| USD | Dollar | Cent | 2 | $19.99 = 1,999 minor units |
| EUR | Euro | Cent | 2 | €19.99 = 1,999 minor units |
| JPY | Yen | N/A | 0 | ¥1,000 = 1,000 minor units |
| KWD | Dinar | Fils | 3 | 19.999 KWD = 19,999 minor units |
| BHD | Dinar | Fils | 3 | 19.999 BHD = 19,999 minor units |
One divide-by-100 shortcut applies two decimal places to every currency to get the major unit. That shortcut breaks on the Japanese yen, which uses zero decimal places, and on the Kuwaiti or Bahraini dinar, which use three.
A payment platform built on that shortcut overcharges or undercharges by a factor of ten the moment it processes a three-decimal currency, and misreports yen amounts by attaching a cents value to a currency that has none. The error reaches beyond a single transaction because regulatory reports, tax filings, and reconciliation exports inherit the same factor-of-ten mistake.
Payment systems usually don’t store $19.99 as “19.99.” They store it as 1999 cents.
Why? Because computers can make mistakes when doing calculations with decimal numbers. Values such as 0.10 and 0.20 cannot always be represented exactly in the binary format computers use for calculations. As a result, adding them can produce a result like 0.30000000000000004 instead of exactly 0.30. Goldberg’s 1991 survey in ACM Computing Surveys remains the canonical reference on this topic.
For a single purchase, a tiny rounding difference might seem harmless. In a payment system handling millions of transactions, however, small errors can add up and create differences between what the system expects and what was actually processed.
Storing amounts as whole numbers avoids this problem. Instead of calculating with $19.99, the system works with the integer 1999. Integer calculations don’t have the same floating-point rounding issues, making them much safer for handling money.
Most of these bugs appear when amounts are converted between major and minor units or between currencies, especially when two systems use different rules for handling those conversions.
A few recurring gaps show up in payment system testing, but three are especially important.
A test suite that asserts status == 200 or status == “success” and stops there will pass even when the transaction succeeded for the wrong amount. Financial software testing checks the value every time: the number of minor units a payment was supposed to move.
Clean, round test inputs, such as $10.00, $25.00, or $100.00, hide this class of bug entirely. Production traffic includes values like $49.995 after a discount is applied, and that single value is where the bug actually surfaces.
Computed in IEEE 754 double-precision floating point, 49.995 is stored as approximately 49.994999999999997, a value fractionally below the number entered. Rounding that value to two decimals with a naive implementation produces $49.99, even though two of the three standard rounding rules (round-half-up and round-half-to-even, also called banker’s rounding) should mathematically produce $50.00 on the true decimal value:
| Rounding rule | Correct result on 49.995 | Naive floating-point result |
|---|---|---|
| Round half up | $50.00 | $49.99 |
| Round half to even (banker’s rounding) | $50.00 | $49.99 |
| Truncate / round down | $49.99 | $49.99 |
The discrepancy only appears with certain values that fall on a rounding boundary. Simple, round-number test data can pass without any issues, while a larger reconciliation may reveal the difference.
A mobile app, a web frontend, and a backend API each format the same underlying value differently: one truncates, one rounds, one applies a locale-specific rule. Checking only one layer means missing the disagreement between the other two. The visible result would be inconsistent numbers on the same transaction.
Tracing a payment end to end is the real test. The value starts with what the user enters, carries through the API request, lands in the database in minor units, reappears on the confirmation screen, and finally shows up in any downstream export, statement, or reconciliation file.
A test that stops at an API response of 200 checks the wrong thing. A mismatch anywhere in that chain is a defect, even if each one looks correct in isolation.
Boundary values surface rounding bugs. A test data set for financial software testing should deliberately include:
Any platform that touches more than one currency needs tests that check the full conversion path:
Testing only the exchange-rate lookup, without testing the rounding and storage steps that follow it, can miss the very bug most likely to make it into production.
A useful check is to convert an amount from a zero-decimal currency to a three-decimal currency and back again, then verify that you get the original amount. If the values don’t match, it usually points to a rounding rule being applied at the wrong stage.
A pre-built multi-currency core ledger can reduce the engineering effort needed to build this kind of infrastructure. But thorough test coverage is still essential.
| Standard functional testing | Fintech-specific testing | |
|---|---|---|
| Definition of correct | Page loads, status code is 200 | The exact amount debited equals the exact amount credited, in the right currency, to the smallest unit |
| Test data | Round numbers | Half-cent boundaries, zero- and three-decimal currencies, negative adjustments |
| Scope of a single test | One service or endpoint | Ledger, gateway, statement export, and reconciliation report checked against each other |
| Regulatory awareness | Rarely a factor | PCI DSS scope, PSD2 authentication rules, audit-trail requirements |
| How failure shows up | A visible error or crash | A one-cent drift that surfaces in a reconciliation report weeks later |
Payment errors aren’t always small rounding differences. Sometimes, a mistake in the payment process can turn into a loss of hundreds of millions of dollars.
One of the most striking examples happened in August 2020, when Citibank was processing payments for a $1.8 billion syndicated loan to Revlon. The bank intended to send lenders about $7.8 million in interest. Instead, an internal processing error caused it to send almost $900 million, effectively paying off the entire loan three years early.
Some lenders returned the money, while others argued that the payment appeared legitimate and kept it. A federal judge initially sided with the lenders, though an appeals court later reversed that decision.
The legal outcome is a separate question. From a payment-testing perspective, the important point is simpler: a process designed to move roughly $8 million ended up moving roughly $900 million, and the controls in place did not catch the error.
That’s why payment QA needs to test more than whether a transaction technically succeeds. The amounts, calculations, conversions, and rules behind the transaction all need to be checked — especially at the points where one system hands data to another.
The stakes scale with the size of the platform, but the exposure is present at every stage:
At every step of a transaction, financial software testing needs to be automated so that it can check monetary values. If there is a difference between a ledger entry and a gateway response, it is immediately marked as a failed build.
Embedding AI directly into QA and CI/CD pipelines is one way to generate test cases for edge cases that are easy to miss manually like partial refunds, currency rounding, timeout retries.
A type of bug that causes a mismatch can be caught by automated checks that compare the amount of a transaction across the ledger, the payment gateway, and any downstream exports.
Cross-system validation like this becomes more valuable as release frequency increases. One documented Kindgeek case of moving from quarterly releases to weekly CI/CD in a regulated fintech environment made automated reconciliation checks part of the release gate itself, ahead of any manual, after-the-fact audit.
As a fintech product expands into new currencies, markets, or configurations, its QA process needs to scale with it. A test suite built around one currency or one product setup can quickly become expensive to maintain as new variations are added.
This is especially important for products that support multiple brands or configurations on the same underlying infrastructure. White-label QA testing, for example, works best when functional regression and third-party integration tests are designed to be brand-agnostic and automated from the start. The same core tests can then be reused across different configurations instead of being rebuilt for each one.
The goal is simple: as the product grows, testing should become more efficient, not more expensive. Testing the tenth currency or fifth brand should require far less effort than testing the first.
Issues like confusing major and minor currency units are exactly the kind of edge cases that can slip through when payment software is tested only at the surface level. Kindgeek has spent more than a decade building and testing financial software within regulated payment environments, including more than 100 shipped products across neobanking, card issuing, and core banking.
Its fintech QA teams work with standards and systems such as PSD2, PCI DSS, and card schemes, helping uncover issues that can have a real impact on transactions, from incorrect currency assumptions to authentication thresholds and payment-flow logic.
With Kindgeek, QA goes beyond checking whether a payment goes through. The team tests how amounts are stored and calculated, how they move through the gateway and ledger, and whether the pieces work together correctly before the product reaches users.
Kindgeek’s QA teams work inside regulated fintech products daily, and build test plans around the failure modes payment systems actually have: multi-currency rounding and ledger-to-gateway drift.
Contact usThe payment bugs that cost the most aren’t always the most obvious. They often happen when different parts of the payment flow handle the same amount differently, whether during calculation, conversion, or recording. In each case, the payment can appear to succeed from start to finish while the amount is still wrong.
The safest approach is to test payments based on how money actually moves through the system. Follow the amount through each stage, test cases where rounding can change the result, and verify each currency’s minor-unit rules instead of carrying assumptions over from previous projects.
The earlier these checks are built into the QA process, the cheaper they are to fix. Finding a one-cent discrepancy in testing is far better than finding it after the payment has reached a customer.
A major unit is the everyday currency amount: a dollar, a euro, a dinar. A minor unit is the smallest fraction of that currency a system represents internally, and the number of decimal places varies: two for USD and EUR, zero for JPY, three for KWD and BHD.
Standard floating-point arithmetic approximates most decimal fractions instead of representing them precisely, which means ordinary decimal math on dollar amounts introduces tiny errors that compound across large transaction volumes. Storing amounts as whole integers in minor units eliminates floating-point discrepancies, making math operations precise.
The most common failure is testing round, clean amounts and missing the values that land right on a rounding boundary, such as one ending in .005 after a discount or tax calculation. These boundary values expose differences between rounding rules, and between the mathematically correct result and what a naive floating-point implementation returns.
Functional testing confirms that a checkout flow works and a page loads correctly. Payment testing goes further, requiring an understanding of how specific currencies round and how refunds interact with fees. This financial knowledge is what regulators and auditors expect to see reflected in software testing.
A web or mobile app’s correctness is visible on screen: buttons, page load etc. QA testing for fintech systems checks what happens beneath the UI: whether a specific amount in a specific currency stays consistent from the frontend through the API, into the ledger, and out to downstream reports. In fintech, a small numerical error can cause problems without triggering an obvious failure.
Fedwire, the US domestic wire system, settles more than $4.7 trillion in transfers a day,…
AI coding assistants speed up individual tasks. AI-native engineering changes how the entire delivery pipeline…
QA doesn't automatically scale the same way your product does. We learned this while building…
Whether the goal is a custom AI agent, a generative AI feature, or a full…
Fintechs report advanced AI adoption at 47%, compared with 30% among incumbent banks, according to…
We reviewed 40+ agencies and shortlisted 10 on verifiable delivery evidence: live listings, case studies,…