Q35 of 38 · Manual & exploratory

What's your approach to testing complex business logic that's hard to specify?

Manual & exploratorySeniorbusiness-logicsbebddgherkinsenior

Short answer

Short answer: Co-design tests with subject-matter experts using example-based specifications. Build a representative table of (input, output) examples, validate with the experts before coding, then drive both implementation and tests from the same examples.

Detail

Complex business logic — pricing engines, eligibility rules, tax, regulatory calculations — is hard to specify because the experts know it as a set of cases, not as a clean rule. Forcing them to write a complete specification is usually counter-productive. The alternative is example-based specification (Specification by Example or BDD).

The process:

  1. Gather examples, not rules. Sit with the SME. "Show me a real payment that gets charged 19% VAT. Now one with 5%. Now one that's exempt. Now an edge case." Capture each as (input, expected output, why). Aim for 30–100 examples covering boundary conditions, special cases, and exceptions. This is your acceptance criteria.
  2. Validate the table with the SME. "Here are 60 examples I've written down. Are any of these wrong? Are there cases I'm missing?" Fix the table until the SME signs off. This is the most valuable step — most "complex logic" bugs are actually specification bugs that surface here.
  3. Convert examples into tests. Each row becomes a test case (parameterised tests work beautifully here).
  4. Drive implementation from the examples. The dev writes code until all examples pass. The tests are now both the spec and the regression suite.
  5. Treat the example table as living documentation. When the rules change, the table changes first.

Tools that fit: Cucumber/Gherkin for human-readable scenarios; parameterised unit tests for tighter, code-first style; decision tables for rule-heavy domains.

Where it breaks down: domains with infinite or near-infinite input spaces (numerical analysis, ML model behaviour) — examples alone don't cover them, you need property-based testing or statistical validation.

// EXAMPLE

vat-examples.feature

Feature: VAT calculation

  Scenario Outline: Standard rates by country and product type
    Given a customer in <country>
    And a <product> sold for £<net>
    When VAT is calculated
    Then the gross amount is £<gross>

    Examples:
      | country | product | net    | gross  |
      | UK      | book    | 10.00  | 10.00  |  # zero-rated
      | UK      | laptop  | 100.00 | 120.00 |  # standard 20%
      | DE      | laptop  | 100.00 | 119.00 |  # standard 19%
      | DE      | ebook   | 10.00  | 10.70  |  # reduced 7%
      | FR      | takeout | 12.00  | 13.20  |  # reduced 10%
      | IE      | book    | 10.00  | 10.00  |  # zero-rated

  Scenario: Reverse charge on B2B intra-EU
    Given a registered business in DE selling to a registered business in FR
    And a £100 net product
    When VAT is calculated
    Then VAT is reverse-charged (zero on invoice)

// WHAT INTERVIEWERS LOOK FOR

Example-based / specification-by-example approach, recognition that the SME validation step catches more spec bugs than implementation bugs, and willingness to use Gherkin or parameterised tests.

// COMMON PITFALL

Saying 'I write tests after the code is done' — for complex logic, the tests *are* the spec, written first.