Not all types of tests belong at every stage of the CI. The testing pyramid is a guide for balancing speed and confidence in your pipeline.
Mike Cohn's testing pyramid remains the best compass for organizing a CI test strategy. At the base: unit tests, numerous, fast, isolated. In the middle: integration tests, fewer in number, verifying that components work well together. At the top: E2E (end-to-end) tests, few in number, slow, verifying critical user flows. The most common mistake is inverting the pyramid: many fragile E2E tests, few reliable unit tests.
Mike Cohn's pyramid: the higher you go, the slower, more costly and fewer the tests.
Unit tests must run in CI on every push, without delay. They must not depend on a database, network or file system. In Java, JUnit 5 + Mockito; in JavaScript, Jest or Vitest. Integration tests verify real interactions — the ORM with a real database (Testcontainers in Java is excellent for this), HTTP calls to mocked APIs. They are slower but remain manageable in CI if well isolated.
E2E tests with Cypress or Playwright are the most fragile and most costly to maintain. Reserve them for critical flows: login, payment, main flow. Run them only before a production deployment, not on every PR. Managing flaky tests is work in itself: track the success rate of each test, quarantine flaky tests, fix them before reintegrating.
- Keep unit tests fast and independent
- Use Testcontainers for integration tests with real services
- Reserve E2E tests for critical flows
- Treat flaky tests as priority bugs
→ See also: CI/CD best practices · ROI of automated tests