Some of the most expensive software bugs produce differences that look almost meaningless.

A total might be off by:

- $0.01
- €0.02
- ₹0.01
- ¥1
- 0.001 KWD

To a tester looking at one transaction, that difference may seem insignificant.

At scale, it can become a serious financial problem.

Consider an application processing millions of transactions.

If a calculation is wrong by even a small amount on every transaction, the accumulated difference can become significant.

And the problem is not limited to payment systems.

Rounding affects:

- ecommerce checkouts
- invoices
- subscriptions
- taxes
- discounts
- commissions
- payroll
- accounting
- refunds
- currency conversion
- financial reports
- marketplaces
- loyalty programs
- shipping calculations
- billing systems
- payment gateways
- dashboards

The difficult part is that rounding bugs are often hidden inside otherwise correct calculations.

For example:

Product price
↓
Discount
↓
Tax
↓
Currency conversion
↓
Rounding
↓
Final amount

Each individual calculation may appear correct.

The final result can still be wrong because the application rounded at the wrong stage.

This is why QA should not treat currency rounding as a formatting problem.

It is a data accuracy and business logic problem.

---

What Is Currency Rounding Testing?

Currency rounding testing verifies that monetary values are calculated, stored, displayed, converted, and persisted according to the application's defined financial rules.

It covers questions such as:

- How many decimal places does a currency support?
- When should a value be rounded?
- Which rounding rule is used?
- Is rounding performed before or after tax?
- Is rounding performed before or after discounts?
- Are intermediate calculations rounded?
- Are negative values handled correctly?
- Does the database preserve the required precision?
- Does the API return the correct amount?
- Does the UI display the same amount?
- Does the payment provider receive the correct amount?
- Does the invoice contain the same amount?
- Does a refund use the same calculation rules?

A basic example:

10.005

Depending on the system's defined precision and rounding policy, this value may become:

10.01

But another system could use a different rounding rule.

The important QA principle is:

Do not assume the mathematically obvious result is the expected result.

The expected result must come from the product's financial rules.

---

Why Rounding Bugs Are So Dangerous

A normal UI defect might cause:

A button appears slightly misaligned.

A rounding defect might cause:

Thousands of customers were charged incorrectly.

The visual difference may be tiny.

The business impact may not be.

Rounding problems can also spread across systems.

Imagine:

Checkout
↓
Billing Service
↓
Payment Gateway
↓
Accounting System
↓
Financial Report

If the checkout calculates:

19.99

but the accounting system receives:

20.00

the problem may not become visible until reconciliation.

This makes financial calculation bugs particularly dangerous.

---

The First Rule: Define the Money Contract

Before writing test cases, QA should understand the application's monetary rules.

Document:

- supported currencies
- decimal precision
- rounding mode
- calculation order
- tax rules
- discount rules
- conversion rules
- storage precision
- display precision
- minimum transaction amount
- maximum transaction amount
- negative amount behavior
- refund behavior
- partial payment behavior
- split payment behavior

For example:

Currency: USD
Decimal places: 2
Rounding: Half-up
Storage: Minor units
Display: 2 decimal places

The exact rules will vary by product.

The important point is that QA should not invent expected values independently of the business specification.

---

Currency Precision Is Not the Same as Display Formatting

One of the most common mistakes is assuming that the number shown to the user is the number stored internally.

For example, the UI might display:

$10.50

But the application might internally represent the amount as:

1050 cents

Or:

10.500000

Or another decimal representation.

Testing should therefore happen at multiple layers.

UI

What does the customer see?

API

What value does the service return?

Database

What value is actually stored?

Payment gateway

What amount is sent externally?

Accounting

What amount is recorded?

These values should follow the system's defined contract.

---

Test Currency Decimal Rules

Different currencies can have different decimal conventions.

Do not build a test suite around the assumption that every currency behaves like USD.

Create test data that includes currencies with different precision requirements.

For example:

| Currency | Example Precision |
|---|---:|
| USD | 2 decimal places |
| EUR | 2 decimal places |
| GBP | 2 decimal places |
| JPY | 0 decimal places |
| KWD | 3 decimal places |

The exact supported currency set depends on the application.

For every supported currency, verify:

- input precision
- calculation precision
- storage precision
- display precision
- payment amount
- refund amount
- report amount

A common defect is implementing one universal rule such as:

round(value, 2)

and applying it to every currency.

That can be incorrect for currencies with different decimal requirements.

---

Test Values Exactly at the Rounding Boundary

Boundary values are particularly important.

Suppose the application rounds to two decimal places.

Test values around the boundary:

10.004
10.005
10.006

Also test:

10.014
10.015
10.016

And values involving multiple decimal positions:

0.001
0.004
0.005
0.006
0.009

The purpose is not simply to test random numbers.

The purpose is to test where the application's rounding decision changes.

---

Test Both Rounding Directions

A good test suite should contain values that round:

Down

and

Up

For example:

10.004 → expected lower value

and:

10.006 → expected higher value

Also test values exactly at the midpoint according to the application's rounding rule.

Do not create only happy-path prices such as:

10.00
20.00
50.00

Those values rarely expose rounding defects.

---

Test the Exact Halfway Value

The halfway value is one of the most important cases.

For two decimal places, values such as:

10.005
20.015
99.995

can reveal differences between rounding strategies.

Depending on the application's defined rule, the result can differ.

Possible rounding strategies include:

- half up
- half down
- half even
- toward zero
- away from zero

The application should have one explicitly defined behavior.

QA should build tests around that rule.

---

Test Negative Monetary Values

Negative amounts are frequently forgotten.

Examples include:

- refunds
- credits
- account adjustments
- chargebacks
- discounts
- accounting corrections

If the system supports negative amounts, test:

-10.004
-10.005
-10.006

Do not assume that the same implementation behaves symmetrically for positive and negative values.

A rounding function can produce surprising results around zero.

Test:

-0.006
-0.005
-0.004
0
0.004
0.005
0.006

This is particularly important for financial adjustments.

---

Test Zero and Near-Zero Values

Small values can expose defects that normal transactions never reveal.

Test:

0
0.001
0.004
0.005
0.009

Also test negative near-zero values where supported.

Check whether the application produces:

0.00

or:

-0.00

A displayed `-0.00` can be a small UI defect, but it can also reveal deeper inconsistencies in calculation logic.

---

Test Decimal Representation

Floating-point arithmetic can introduce unexpected precision behavior.

For example, many programming languages use binary floating-point representations for ordinary numeric types.

That means calculations that look simple in decimal arithmetic may not be represented exactly internally.

A classic example is:

0.1 + 0.2

which can produce a value extremely close to, but not exactly, `0.3` in binary floating-point systems.

This does not automatically mean the application is broken.

What matters is whether the system uses an appropriate monetary representation and applies the required rounding rules.

QA should therefore test the actual output of financial calculations rather than trusting the language's default number type.

---

Test Addition of Monetary Values

Start with simple arithmetic.

For example:

10.10
20.20
30.30

Expected:

60.60

Then introduce values that require precision handling:

10.005
20.005
30.005

The expected result depends on where and when the application rounds.

Test both:

Round before addition

round(10.005)
+
round(20.005)

and:

Add before rounding

round(10.005 + 20.005)

These can produce different results.

The product specification must define which behavior is correct.

---

Test Tax Calculation

Tax is one of the most common sources of rounding problems.

Suppose:

Product = 19.99
Tax = 18%

The application calculates:

19.99 × 0.18

The resulting value may contain more precision than the customer-facing currency supports.

QA needs to know:

When is the tax rounded?

Possible strategies include:

Calculate tax per item
↓
Round each item tax
↓
Add taxes

or:

Add item totals
↓
Calculate total tax
↓
Round once

These can produce different totals.

The test suite should explicitly cover the application's chosen method.

---

Test Tax Per Line vs Tax on the Total

Consider:

Item A = 10.01
Item B = 10.01

If tax is calculated separately:

Tax A
+
Tax B

the result can differ from:

Total = 20.02
Tax on total

Neither approach is automatically correct.

The important thing is consistency with the business and regulatory rules that apply to the product.

Build tests that compare:

- line-level tax
- order-level tax
- invoice-level tax
- displayed tax
- stored tax

---

Test Discounts Before and After Tax

Discount ordering can dramatically change the final amount.

Consider:

Product
↓
Discount
↓
Tax

versus:

Product
↓
Tax
↓
Discount

The final values may differ.

QA should therefore test the calculation sequence explicitly.

For example:

Price = 100
Discount = 10%
Tax = 18%

Verify the expected result according to the application's business rules.

Then test:

- percentage discount
- fixed discount
- multiple discounts
- maximum discount
- minimum order threshold
- tax-exempt items
- discounted taxable items

---

Test Multiple Discounts

Multiple discounts are another common source of calculation errors.

For example:

Price = 100

Discount 1:

10%

Discount 2:

20%

Does the system calculate:

100 × 0.70

or:

100 - 10
= 90

then:

90 - 18
= 72

Those are mathematically equivalent in this simple case.

But rounding, minimum discounts, caps, and fixed-value promotions can change the outcome.

Test combinations such as:

- percentage + percentage
- fixed + percentage
- percentage + fixed
- coupon + loyalty discount
- promotion + tax exemption

---

Test Currency Conversion

Currency conversion introduces another rounding layer.

For example:

100 USD
×
FX rate
=
EUR amount

Then:

Round EUR amount

But the application may have:

- FX rate precision
- markup
- conversion fee
- currency precision
- final rounding rule

Test each component independently.

For example:

Source amount
↓
Exchange rate
↓
Converted amount
↓
FX fee
↓
Final amount
↓
Currency rounding

Do not validate only the final displayed number.

---

Test Exchange Rates With Deterministic Data

Never make your core rounding tests depend on live exchange rates.

Live rates can change.

That makes the expected result unstable.

Instead, use deterministic test data.

For example:

USD → EUR
Rate = 0.912345

Then calculate expected values independently.

This allows the test to determine whether the system:

- applied the rate correctly
- applied the fee correctly
- rounded at the correct stage

Live exchange-rate integration should have separate tests.

---

Test Fees and Commissions

Many systems calculate fees using:

- percentage
- fixed amount
- minimum fee
- maximum fee
- tiered fee

Example:

Transaction = 99.99
Fee = 2.9% + fixed fee

Test:

- very small transaction
- normal transaction
- large transaction
- fee minimum
- fee maximum
- exact threshold
- just below threshold
- just above threshold

Rounding should be checked after every business rule where the specification requires it.

---

Test Refund Calculations

Refunds are particularly important because the original transaction may already contain:

- discounts
- taxes
- fees
- currency conversion
- rounding

A full refund should normally follow the product's defined financial rules.

A partial refund is more complicated.

For example:

Order = 100
Discount = 10
Tax = 18

Then a customer refunds one of several items.

What amount should be returned?

Test:

- full refund
- partial refund
- multiple partial refunds
- refund after discount
- refund after tax
- refund with fees
- refund in converted currency

Also verify that repeated refund requests cannot exceed the refundable amount.

---

Test Split Payments

If the application supports split payments, rounding becomes even more interesting.

Suppose:

Total = 100.00

Three users split the payment equally.

Mathematically:

100 / 3 = 33.333...

But the currency may only support two decimal places.

Possible allocation:

33.33
33.33
33.34

The system needs a defined allocation rule.

QA should verify:

Sum of allocations = original total

This is more important than simply checking that each individual amount looks reasonable.

---

Test Percentage Allocation

The same principle applies to percentages.

Suppose:

Total = 100

Allocation:

33%
33%
34%

Expected:

33
33
34

But if percentages or amounts contain more precision, rounding can create discrepancies.

Always test:

Sum of parts = expected total

This is a powerful invariant for financial testing.

---

Test Invariants Instead of Only Expected Numbers

One of the best ways to test financial calculations is to define invariants.

Examples:

Total invariant

Sum(line items) + tax - discount = final total

Refund invariant

Total refunds ≤ original refundable amount

Split payment invariant

Sum(payment parts) = order total

Balance invariant

Opening balance + credits - debits = closing balance

Conversion invariant

Converted amount follows the defined rate and rounding rule

Invariants are powerful because they catch entire classes of bugs.

A test may not know every possible output in advance.

But it can still know what must always remain true.

---

Test Database Storage Precision

The database layer can introduce its own rounding behavior.

For example, an application may calculate:

19.999999

but store:

20.00

depending on the database column definition.

Test:

- database precision
- database scale
- insert behavior
- update behavior
- aggregation behavior
- serialization behavior

Also test values near the database boundary.

For example, if the database supports:

DECIMAL(12,2)

test:

9999999999.99

and values beyond the supported range.

The application should reject values that cannot be represented safely rather than silently corrupting them.

---

Test API Serialization

The database might store:

10.50

The API could return:

10.5

or:

"10.50"

or:

10.5000

The correct representation depends on the API contract.

Do not assume that formatting differences are harmless.

If clients depend on a fixed monetary representation, the contract should define it.

Test:

- numeric vs string representation
- decimal places
- null handling
- negative values
- zero
- large values
- currency code

For example:

{
"amount": "19.99",
"currency": "USD"
}

can communicate monetary intent differently from:

{
"amount": 19.99
}

The API contract should make the representation explicit.

---

Test UI Formatting Separately From Calculation

A calculation can be correct while the UI displays it incorrectly.

For example:

API:

1234.50

UI:

$1,234.5

Or:

$1234.50

Or:

1.234,50 €

Depending on locale.

Test:

- currency symbol
- decimal separator
- thousands separator
- decimal places
- negative formatting
- zero formatting
- locale
- currency code

Do not confuse display formatting with financial calculation.

A UI can display a rounded value while the underlying API contains the correct precision.

---

Test Locale Differences

International applications create another layer of risk.

For example:

US:

1,234.56

Many European locales:

1.234,56

Some systems may use:

1 234,56

The underlying amount should remain consistent.

Test the same monetary value across:

- English
- European locales
- Asian locales
- supported regional formats

Also test that parsing user-entered values does not change the amount.

---

Test Currency Symbols

Do not assume the symbol uniquely identifies the currency.

For example, `$` can represent multiple currencies.

Where appropriate, verify:

- currency code
- symbol
- locale
- amount

For financial applications, displaying:

$100

may be insufficient if the user could be operating in different dollar-denominated currencies.

---

Test Large Monetary Values

Small values are not the only risk.

Test large amounts near system limits.

Examples:

999.99
9,999.99
999,999.99
9,999,999.99
maximum supported value

Look for:

- overflow
- truncation
- scientific notation
- database errors
- API serialization problems
- incorrect formatting
- rounding differences

Large-value testing is particularly important for business-to-business applications.

---

Test Very Small Monetary Values

Also test values close to zero.

Examples:

0.01
0.02
0.05
0.09
0.10

And where supported:

0.001
0.005
0.009

Small values often expose:

- minimum transaction bugs
- rounding to zero
- negative zero
- fee calculation errors
- discount calculation errors

---

Test Aggregation and Reporting

A major financial bug can appear when individual transactions are correct but aggregated reports are wrong.

For example:

Transaction A:

10.004

Transaction B:

10.004

Should the report calculate:

round(10.004) + round(10.004)

or:

round(10.004 + 10.004)

The result can differ depending on the application's accounting rules.

Test:

- transaction totals
- daily totals
- monthly totals
- invoice totals
- dashboard totals
- exported totals
- accounting totals

Verify that aggregation rules are consistent.

---

Test CSV and Report Exports

Financial reports frequently introduce formatting and precision defects.

For example:

UI:

€1,234.50

CSV:

1234.5

Database:

1234.5000

Accounting system:

1234.50

These values may represent the same amount, but the downstream system may require a specific format.

Test:

- CSV
- Excel
- PDF
- API
- UI
- accounting exports

For every output, verify the amount and currency.

---

Test Payment Gateway Amounts

The final payment request is one of the most important assertions.

Suppose the customer sees:

$19.99

The payment gateway should receive the amount according to its API contract.

For gateways using minor units:

$19.99

may be represented as:

1999

The test should verify the transformation.

Do not rely only on the UI.

Inspect the outbound API request or use a test gateway environment.

---

Test Double-Rounding

Double-rounding is a subtle but important problem.

Imagine a system:

1. calculates a high-precision amount
2. rounds it
3. performs another calculation
4. rounds again

The final value may differ from performing the calculation at full precision and rounding once.

For example:

Raw calculation
↓
Round
↓
Tax
↓
Round

versus:

Raw calculation
↓
Tax
↓
Round once

The expected result depends on the business rules.

QA should explicitly test where rounding occurs.

---

Test Rounding Order

Create tests that intentionally distinguish between:

Round A → Calculate B

and:

Calculate B → Round

For example:

Price
↓
Discount
↓
Round
↓
Tax

versus:

Price
↓
Discount
↓
Tax
↓
Round

This is one of the most valuable areas of financial testing because both implementations can look reasonable in code review.

Only the business rule determines which is correct.

---

Test Repeated Calculations

Some applications repeatedly transform amounts.

For example:

USD
↓
EUR
↓
GBP
↓
USD

Every conversion and rounding operation can introduce small differences.

If the product supports such workflows, test whether repeated conversions are expected to preserve a particular invariant.

Do not assume:

USD → EUR → USD

will always produce the original amount exactly.

Currency conversion is not necessarily reversible once rounding has occurred.

The important thing is that the product's expected behavior is clearly defined.

---

Test API and UI Against the Same Expected Value

One useful technique is to maintain an independent expected-value calculator for test data.

For example:

Input:
price = 19.99
tax = 18%
discount = 10%

The test fixture calculates the expected result independently.

Then compare:

Expected
vs
API
vs
UI

This is safer than generating the expected result using the same production calculation function.

If your test uses the same flawed calculation as the application, both can be wrong while the test passes.

---

Avoid Circular Test Calculations

This is an important automation principle.

Bad approach:

expected = application.calculate(amount)
actual = application.calculate(amount)

Result:

expected == actual

Of course it does.

The test has proven almost nothing.

Instead, expected values should come from:

- an independent calculation
- approved test fixtures
- a specification
- known financial examples
- a separate reference implementation

For monetary logic, independence is particularly important.

---

Build a Boundary-Focused Test Dataset

Instead of creating hundreds of random amounts, build a deliberate dataset.

Example:

| Category | Examples |
|---|---|
| Zero | 0 |
| Small | 0.01, 0.05 |
| Halfway | 10.005 |
| Just below | 10.004 |
| Just above | 10.006 |
| Negative | -10.005 |
| Large | 9999999.99 |
| Maximum | System maximum |
| Currency-specific | JPY, KWD |
| Discount | 10%, 33.33% |
| Tax | 5%, 18%, 20% |
| Conversion | Deterministic FX rate |

This gives much more useful coverage than random values alone.

---

Automating Currency Rounding Tests

Currency tests are excellent candidates for data-driven automation.

Example:

test_cases = [
{
"currency": "USD",
"input": "10.004",
"expected": "10.00"
},
{
"currency": "USD",
"input": "10.005",
"expected": "10.01"
},
{
"currency": "USD",
"input": "10.006",
"expected": "10.01"
}
]

Then the same test logic can execute against many datasets.

This is easier to maintain than writing individual tests for every value.

---

Use Independent Decimal Arithmetic for Expected Values

When building test utilities, use a decimal-aware approach rather than relying on ordinary floating-point calculations where precision matters.

The expected-value calculation should reflect the application's defined financial rules.

For example, a test helper might conceptually do:

amount
↓
Decimal representation
↓
Apply business calculation
↓
Apply defined rounding rule
↓
Expected amount

The application under test should be calculated independently.

This separation helps detect arithmetic defects rather than reproduce them.

---

AI-Assisted Currency Testing

AI can help QA teams discover rounding scenarios that are easy to miss.

For example, given:

Price
Discount
Tax
Currency
FX conversion
Payment

an AI-assisted testing system could generate scenarios involving:

- rounding boundaries
- different currencies
- negative values
- large values
- partial refunds
- split payments
- discount combinations
- tax combinations
- conversion sequences

AI can also inspect requirements and identify questions such as:

Is tax rounded per line item or at order level?
Does the refund use the original exchange rate?
Are amounts stored in major or minor currency units?
What happens when a split payment produces fractional cents?

These questions are often more valuable than simply generating more test cases.

AI should help expose uncertainty.

It should not invent financial rules.

For monetary workflows, the expected behavior must come from the product and business specification.

---

Common Currency Testing Mistakes

Mistake 1: Testing only two decimal places

Not every currency follows the same decimal convention.

Test the currencies your product actually supports.

---

Mistake 2: Testing only display values

A UI showing:

$10.50

does not prove that the backend stored or charged:

10.50

Validate the complete data path.

---

Mistake 3: Ignoring negative values

Refunds and credits frequently expose rounding defects.

Test them.

---

Mistake 4: Rounding after every calculation

More rounding is not necessarily safer.

The correct rounding point depends on the financial specification.

---

Mistake 5: Using live FX rates in core tests

Live rates make expected values unstable.

Use deterministic rates for calculation tests.

---

Mistake 6: Reusing production calculation logic for expected values

This can create circular tests.

Expected values should be independently derived.

---

Mistake 7: Ignoring split payments

Dividing an amount among multiple parties can create fractional minor units.

Test allocation rules explicitly.

---

Mistake 8: Testing only one transaction

Financial defects can emerge during:

- aggregation
- refunds
- reporting
- reconciliation
- repeated conversions

Test the full lifecycle.

---

A Practical Currency Rounding Test Matrix

| Area | Test |
|---|---|
| Precision | Supported decimal places |
| Boundary | Just below rounding threshold |
| Boundary | Exactly at threshold |
| Boundary | Just above threshold |
| Negative | Negative midpoint values |
| Zero | Zero and near-zero values |
| Currency | Different currency precisions |
| Tax | Tax rounding |
| Discount | Discount rounding |
| Conversion | FX calculation |
| Fees | Percentage and fixed fees |
| Refund | Full refund |
| Refund | Partial refund |
| Split | Allocation remainder |
| Storage | Database precision |
| API | Monetary serialization |
| UI | Currency formatting |
| Reports | Aggregation |
| Gateway | Outbound payment amount |
| Large values | Maximum supported amount |
| Small values | Minimum supported amount |
| Invariants | Sum of parts equals total |

---

Example End-to-End Test

Imagine an ecommerce order:

Product A = 19.99
Product B = 29.99

Discount:

10%

Tax:

18%

Currency:

USD

The test should not simply check:

Final total = expected

It should validate the complete calculation contract.

Step 1: Add products

Verify:

19.99 + 29.99 = 49.98

Step 2: Apply discount

Verify the defined discount calculation.

Step 3: Apply tax

Verify whether tax is calculated before or after discount according to the product rules.

Step 4: Apply rounding

Verify the exact rounding point.

Step 5: Check API

Verify:

amount
currency

Step 6: Check UI

Verify the displayed total.

Step 7: Check payment request

Verify the gateway receives the correct amount.

Step 8: Check database

Verify the persisted transaction.

Step 9: Check invoice

Verify the invoice total.

Step 10: Check refund

Refund the order and verify the correct amount is returned.

This creates a much stronger test than simply checking the checkout screen.

---

Currency Rounding Testing Checklist

Calculation

- [ ] Correct decimal precision
- [ ] Correct rounding mode
- [ ] Correct calculation order
- [ ] Correct intermediate precision
- [ ] No unintended double-rounding
- [ ] Correct negative value behavior
- [ ] Correct zero behavior

Currency

- [ ] Every supported currency tested
- [ ] Currency-specific precision verified
- [ ] Currency code verified
- [ ] Currency symbol verified
- [ ] Locale formatting verified

Tax

- [ ] Tax calculation verified
- [ ] Tax rounding verified
- [ ] Line-level tax tested
- [ ] Order-level tax tested
- [ ] Discount/tax ordering tested

Discounts

- [ ] Percentage discounts
- [ ] Fixed discounts
- [ ] Multiple discounts
- [ ] Maximum discount
- [ ] Minimum order threshold
- [ ] Discount rounding

Payments

- [ ] Gateway amount verified
- [ ] Minor-unit conversion verified
- [ ] Minimum payment tested
- [ ] Maximum payment tested
- [ ] Duplicate payment protection tested

Refunds

- [ ] Full refund
- [ ] Partial refund
- [ ] Multiple refunds
- [ ] Refund after discount
- [ ] Refund after tax
- [ ] Refund currency verified

Data

- [ ] Database precision verified
- [ ] API representation verified
- [ ] UI representation verified
- [ ] Reports verified
- [ ] Export values verified
- [ ] Accounting values verified

Automation

- [ ] Boundary dataset created
- [ ] Expected values independently calculated
- [ ] Deterministic FX rates used
- [ ] Data-driven tests implemented
- [ ] Financial invariants asserted

---

Final Thoughts

Currency rounding bugs are rarely about whether a number looks right on a screen.

They are about whether the entire financial calculation remains correct from beginning to end.

A strong QA strategy follows the money:

Input
↓
Price
↓
Discount
↓
Tax
↓
Fees
↓
Currency Conversion
↓
Rounding
↓
Payment
↓
Database
↓
Invoice
↓
Refund
↓
Reporting

The most valuable tests are not random monetary values.

They are the values around the points where business rules change.

Test:

- just below the boundary
- exactly at the boundary
- just above the boundary
- positive values
- negative values
- zero
- very small amounts
- very large amounts
- different currencies
- tax and discount combinations
- partial refunds
- split payments
- currency conversion
- aggregation

Most importantly, define the financial rules before testing them.

QA should not guess whether a value should round up or down.

The product specification should tell you.

Your tests should then make sure the application follows that rule consistently across the UI, API, database, payment gateway, reports, and downstream systems.

Because in financial software, a one-cent defect is not necessarily a small defect.

The real question is:

How many times will that one-cent defect happen?