Integration and End-to-End Testing
Tests that check whether the components of a trading system actually work correctly together, and whether the full pipeline from data in to orders out behaves as expected — the layers above individual unit tests.
Prerequisites: Unit Testing Fundamentals, Test Fixtures and Mocking
A signal-generation function passes every unit test in isolation. A risk-sizing function passes every unit test in isolation. An order-execution function passes every unit test in isolation. Wire the three together into a live pipeline and the whole thing produces zero trades, because the signal function outputs a value in the range -1 to 1 and the risk-sizing function was written expecting a raw z-score, so every signal gets silently clipped to nothing before it ever reaches the order function. Each piece is individually correct; the seams between them are not. Unit tests, by design, check components one at a time with everything around them faked out — they cannot catch a mismatch in what one component hands to the next, because that handoff is exactly the part they don't exercise.
Integration testing checks that two or more real components work correctly together, without necessarily running the whole system: does the signal function's output actually get consumed correctly by the risk-sizing function, with both running for real, not mocked out? End-to-end (E2E) testing goes further, running an entire realistic pipeline — data in, through every stage, to an order (or a simulated order) out — as close to how the real system would run as practical, checking the whole chain rather than any one link.
Worked example. A team's unit tests confirm the signal function returns correct values for known inputs, and separately confirm the risk-sizing function correctly converts a z-score into a position size. Both suites are green. An integration test then feeds the actual output of the signal function directly into the actual risk-sizing function — no mocks on either side — and asserts the final position size is nonzero for a clearly bullish signal. This test immediately fails, exposing the unit mismatch that neither unit test alone could see, because each was tested against inputs someone assumed were correct rather than the real output of its actual upstream neighbor. An end-to-end test goes one step further: replaying a full day of historical market data through the entire pipeline — signal, sizing, a simulated execution layer — and asserting the day ends with a plausible set of trades and a P&L that isn't wildly out of range, catching not just interface mismatches but issues that only appear when everything runs together over time, like a memory leak or a state variable that doesn't reset between days.
What this means in practice
Unit tests are cheap and fast and should form the bulk of a test suite; integration and end-to-end tests are slower, more brittle, and more expensive to maintain, so they're used more sparingly — enough to cover the critical seams and the full pipeline's basic sanity, not to duplicate what unit tests already check. A system with excellent unit test coverage but no integration tests can still ship a broken pipeline, because "every part works" and "the parts work together" are different claims.
Unit tests verify one component in isolation; integration tests verify that real components work together correctly at their interfaces; end-to-end tests verify the full pipeline behaves sensibly start to finish. A passing unit test suite says nothing about whether the pieces actually connect correctly — that's what integration testing is for.
Practice in interviews
Further reading
- Fowler, Martin. "TestPyramid", martinfowler.com