Financial calculation functions — rounding, interest accrual, fee application — are high-stakes and frequently modified. Without unit tests that cover zero amounts, min/max boundary values, and rounding-boundary inputs like $10.005, a refactor that silently changes behavior at those boundaries will ship undetected. ISO 25010 maintainability requires that critical business logic be verifiable without running the full application. Missing edge-case coverage is the most common root cause of financial bugs found only in production, often after incorrect charges have been issued.
Info because absent tests don't cause immediate failures but increase the probability of undetected regressions in financial calculation logic during future changes.
Create src/lib/finance.test.ts (or equivalent) and include at minimum three edge-case categories: zero inputs, boundary amounts, and rounding midpoints.
// src/lib/finance.test.ts
import { calculateInterest, roundInterestCents } from './finance';
describe('calculateInterest', () => {
it('returns 0 for zero principal', () =>
expect(calculateInterest(0, 0.05)).toBe(0));
it('handles maximum allowed amount', () =>
expect(calculateInterest(99999, 0.05)).toBeGreaterThan(0));
it('applies banker rounding at 0.5 cent boundary', () =>
expect(roundInterestCents(100.5)).toBe(100)); // rounds to even
it('produces integer output', () =>
expect(Number.isInteger(roundInterestCents(10.335))).toBe(true));
});
Run tests in CI via npm test and gate merges on the test step passing.
ID: finserv-form-validation.error-edge-cases.calculation-testing
Severity: info
What to look for: Count all financial calculation functions (interest, fees, tax, rounding, conversions). For each, check whether a corresponding test file exists in __tests__/, test/, or alongside as .test.ts/.spec.ts. Count the test cases and classify each as happy-path or edge-case (zero amounts, min/max limits, rounding boundaries like $0.005, negative inputs). Report: "X of Y financial functions have tests; Z edge-case scenarios covered."
Pass criteria: At least 100% of financial calculation functions have unit tests. Tests include at least 3 edge-case categories: zero amounts, min/max boundary values, and rounding boundaries (e.g., $10.005). No more than 0 financial functions lack test coverage entirely.
Fail criteria: Any financial calculation function has no test file, or tests cover only happy-path scenarios with fewer than 3 edge-case categories.
Skip (N/A) when: The project has no financial calculations (0 financial calculation functions found), or calculations are trivial (single multiplication with no rounding).
Detail on fail: Example: "No tests found for interest calculations. Only happy-path scenarios tested, no edge cases like $0.005 rounding."
Cross-reference: The no-float-accumulation check verifies integer arithmetic at runtime; this check verifies those patterns are tested to prevent regressions.
Remediation: Write comprehensive tests in src/lib/finance.test.ts:
In src/lib/finance.test.ts:
import { calculateInterest, bankersRound } from './finance';
describe('calculateInterest', () => {
it('should handle zero principal', () => {
expect(calculateInterest(0, 0.05)).toBe(0);
});
it('should round correctly at 0.005', () => {
expect(bankersRound(10000.5)).toBe(10001);
});
it('should handle maximum amounts', () => {
const max = 999999; // $9,999.99
expect(calculateInterest(max, 0.05)).toBeLessThanOrEqual(max);
});
it('should not accumulate floating-point errors', () => {
let balance = 100000;
for (let i = 0; i < 100; i++) {
balance = Math.round(balance * 1.001);
}
expect(balance % 1).toBe(0);
});
});