Skip to main content
Software Testing beginner Lesson 1 of 3

Testing Strategy & Test Pyramid (Beginner)

Learn how to choose the right tests: unit, integration, end-to-end—plus reliability and speed tradeoffs.

Theory

A good testing strategy optimizes for:

  • confidence (catch bugs before release),
  • speed (fast feedback),
  • cost (time to maintain tests),
  • debuggability (tests tell you what broke).

The Test Pyramid (practical guideline)

  • Unit tests: fast, isolate logic, run often
  • Integration tests: verify interactions (DB, queues, APIs)
  • End-to-end (E2E): verify critical paths (UI/API flows)

Rule of thumb:

  • many unit tests
  • fewer integration tests
  • very few E2E tests

What “good” unit tests look like

  • Test one behavior per case
  • Avoid heavy setup/IO
  • Use deterministic inputs
  • Name tests by behavior: should_return_total_when_items_added

Keep integration tests stable

  • Use test containers / ephemeral DBs where possible
  • Seed deterministic data
  • Control time (clock abstraction)
  • Avoid external network dependencies

Code Example (JS/TS: unit test with deterministic clock)

// price.ts
export function applyDiscount(subtotal: number, percent: number) {
  return subtotal * (1 - percent / 100);
}

// price.test.ts
import { applyDiscount } from "./price";

test("should apply percent discount correctly", () => {
  expect(applyDiscount(200, 10)).toBe(180);
});

Practice

  1. Pick a small feature (e.g., “create user profile”).
  2. Write:
    • 5 unit test cases for pure logic
    • 2 integration tests for DB boundary (CRUD)
    • 1 E2E test for the critical flow
  3. Identify which failures are likely to be “fast” vs “slow” and adjust your pyramid.

Common pitfalls

  • Only writing E2E tests (slow + flaky)
  • Snapshot tests without meaningful assertions
  • Tests that depend on time/randomness without control
  • Brittle mocks that break during refactors

Frequently Asked Questions

Should I always aim for 80% unit tests?
Not blindly. Aim for the pyramid that matches your risk: more unit tests for logic, more integration tests for boundaries, and fewer E2E tests for critical user flows.
Why do end-to-end tests fail frequently?
They touch more systems (network, time, external dependencies). Keep them small, stable, and mock what you can.