Post

The Testing Pyramid: Wrapping Up with CI/CD and Best Practices - Part 5

Software testing is more than writing a few unit tests and hoping for the best. To deliver reliable software, teams need a balanced testing strategy — one that combines Unit, Integration, and End-to-End (E2E) tests in the right proportions. This is where the Testing Pyramid comes in.

In this final part of our testing series, we’ll:

  • Understand the Testing Pyramid model.
  • Explore how to balance different types of tests.
  • Learn how to integrate testing into CI/CD pipelines.
  • Review best practices for building a sustainable testing culture.

The Testing Pyramid Explained

The Testing Pyramid (popularized by Mike Cohn) is a metaphor for structuring automated tests:

1
2
3
4
5
6
7
        ▲
        |   End-to-End (fewest, slowest)
        |
        |   Integration (moderate amount, balanced)
        |
        |   Unit Tests (largest base, fastest)
        ▼

1. Unit Tests (Foundation)

  • Fast, cheap, and precise.
  • Cover small pieces of logic in isolation.
  • Should make up 60–70% of your automated test suite.

Example: Testing a function that calculates interest rates.

2. Integration Tests (Middle Layer)

  • Validate how components interact.
  • Cover database queries, API requests, or service orchestration.
  • Should make up 20–30% of your test suite.

Example: Ensuring your API endpoint correctly fetches data from the database and formats the response.

3. End-to-End Tests (Top)

  • Simulate real user flows across the full stack.
  • Catch bugs unit or integration tests can’t.
  • Should make up 10–15% of your suite (because they’re slow and expensive).

Example: A test where a user logs in, adds a product to their cart, and completes checkout.

Integrating Tests into CI/CD Pipelines

Automated tests are only valuable if they’re run consistently. Modern software teams embed them into CI/CD pipelines.

Step 1: Run Unit Tests Early

  • Execute on every commit or pull request.
  • Fail fast: block merges if unit tests fail.

Step 2: Run Integration Tests on Build/Deploy

  • Run after the app compiles successfully.
  • Can use a containerized test environment with mock or staging databases.

Step 3: Run End-to-End Tests on Staging

  • Triggered before production deployment.
  • Some teams run smoke E2E tests in production (carefully) to ensure critical flows still work.

Example CI/CD Flow (GitHub Actions / GitLab / Jenkins):

1
2
3
4
5
6
7
8
9
10
11
12
13
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - name: Install dependencies
        run: npm install
      - name: Run unit tests
        run: npm test -- --unit
      - name: Run integration tests
        run: npm test -- --integration
      - name: Run e2e tests
        run: npm run test:e2e

Best Practices for a Balanced Testing Strategy

1. Follow the Pyramid, Not the Ice Cream Cone

  • Too many E2E tests = slow, brittle pipeline.
  • Too few unit tests = shaky foundation.
  • Balance is key.

2. Use Test Doubles Wisely

  • Mocks/Stubs in unit tests to isolate dependencies.
  • Minimal mocking in integration tests — rely on real services where possible.

3. Make Tests Deterministic

  • Tests should always produce the same result.
  • Avoid flaky tests (caused by race conditions, timeouts, or external dependencies).

4. Keep Tests Fast

  • Aim for seconds, not minutes.
  • Developers won’t run slow tests locally.

5. Automate Everything in CI/CD

  • Manual testing has its place, but regression checks must be automated.
  • CI/CD pipelines should be your safety net before production.

6. Monitor and Improve Test Coverage

  • Coverage isn’t everything, but low coverage usually indicates gaps.
  • Focus on critical paths rather than chasing 100%.

7. Treat Tests as Code

  • Tests should be maintainable, reviewed, and refactored like production code.
  • Avoid “test rot” where tests become outdated or ignored.

Final Thoughts

The journey from unit → integration → E2E tests gives you confidence at every level of your system.

  • Unit tests keep your building blocks solid.
  • Integration tests ensure the blocks fit together.
  • E2E tests confirm the entire structure works as intended.

By following the Testing Pyramid, integrating tests into CI/CD pipelines, and practicing discipline in writing effective tests, you’ll achieve:

  • Faster feedback loops.
  • Fewer production bugs.
  • Higher developer confidence.
  • Happier end-users.

Testing isn’t just about catching bugs, it’s about building trustworthy software at scale.

Next Steps for You:

  • Audit your current test suite.
  • See if you’re over-relying on one type of test.
  • Gradually reshape your suite into a pyramid, not an ice cream cone.
This post is licensed under CC BY 4.0 by the author.