Bonaventure OgetoBy Bonaventure Ogeto|

Test Coverage Targets for Payment Code

Payment code coverage targets: webhook handler (critical business logic) → 100% branch coverage; amount/commission calculation functions → 100% branch coverage; checkout initiation → 90%+; error handling paths → 80%+; frontend checkout UI → 60-70% is acceptable (covered by E2E tests). Use Istanbul/nyc (JS) or coverage.py (Python) to measure. Block merges if webhook handler coverage drops below 90%.

Payment Code Coverage Target Matrix

Code ComponentTarget CoverageWhy
Webhook signature validation 100% Security-critical — missing this allows fake events
Webhook event routing (charge.success, etc.) 100% branches Each event type triggers different business logic
Order fulfillment after payment 100% branches Bugs here mean unfulfilled orders or double fulfillment
Amount/commission calculations 100% branches Rounding bugs cost money — cover all number edge cases
Checkout API call construction 90%+ Ensure correct parameters are sent to Paystack
Error handling (network, 5xx) 80%+ Prevent silent failures and 500 responses to customers
Idempotency checks 100% Duplicate processing = financial data corruption
Transfer payout logic 90%+ Wrong recipient or amount = real financial loss
Frontend checkout UI 60-70% E2E tests cover the full user flow

Setting Coverage Thresholds in Jest

// jest.config.js
module.exports = {
  collectCoverage: true,
  coverageDirectory: 'coverage',
  collectCoverageFrom: [
    'src/**/*.{js,ts}',
    '!src/**/*.test.{js,ts}',
    '!src/types/**',
  ],
  coverageThreshold: {
    // Global minimum
    global: {
      branches: 80,
      functions: 85,
      lines: 85,
      statements: 85,
    },
    // Per-file minimums for critical payment code
    './src/webhooks/paystack-handler.js': {
      branches: 100,
      functions: 100,
      lines: 100,
      statements: 100,
    },
    './src/payments/fulfillment.js': {
      branches: 100,
      functions: 100,
      lines: 100,
      statements: 100,
    },
    './src/payments/calculations.js': {
      branches: 100,
      functions: 100,
      lines: 100,
      statements: 100,
    },
  },
};

Learn More

Key Takeaways

  • Webhook handler business logic should have 100% branch coverage — every code path that handles money must be tested.
  • Amount and commission calculation functions need 100% branch coverage, including edge cases (0 amount, max amount, rounding).
  • Checkout initiation code (API call construction) should be at 90%+ coverage.
  • Error handling paths (network errors, 5xx from Paystack, invalid response format) need dedicated tests — do not rely on the happy path to cover these.
  • Frontend payment UI can have 60-70% coverage — E2E tests cover the rest.
  • Set coverage thresholds in your test config (Jest coverageThreshold, pytest-cov --fail-under) to block low-coverage merges.

Frequently Asked Questions

Is 100% coverage achievable for a webhook handler?
Yes — webhook handlers are pure logic functions with a finite number of input combinations. Write a test for each event type you handle (charge.success, charge.failed, etc.), each branch condition (metadata missing, order not found, duplicate reference), and each error case. 100% branch coverage is realistic and worth the effort for money-moving code.
Does high test coverage mean my payment code is secure?
Coverage measures which code paths are tested, not how well they are tested. 100% coverage with poor assertions means nothing. A 90% covered webhook handler with rigorous assertions (testing that the right DB columns update, the right amounts are recorded) is better than 100% coverage with "expect(result).toBeTruthy()" everywhere.
Should I measure line coverage or branch coverage for payment code?
Branch coverage is more meaningful for payment code. A function with an if/else might have 100% line coverage if tests exercise both the if and else code, but if you only test one branch, you have 50% branch coverage. Branch coverage catches untested conditional logic that line coverage misses.
What is a good coverage target for a first-time payment integration?
Start with 80% statement coverage globally, and set per-file 100% for webhook handler and amount calculation files. As you add more tests, raise the global threshold. The key is to start with thresholds and enforce them in CI — even imperfect targets are better than no targets.

Ready to build real-world apps?

Join the McTaba Labs full-stack marathon (4 months full-time · 6 months part-time). Learn M-Pesa, USSD, and WhatsApp engineering while shipping 8 production apps.

Apply to the McTaba Marathon