Testing Quick Reference
This is a condensed reference for the terms and rules of thumb that come up constantly in day-to-day testing work: the testing pyramid's three levels, the AAA (Arrange-Act-Assert) pattern for structuring individual tests, and the distinction between test doubles (mocks, stubs, fakes, spies) that's frequently blurred in casual conversation but matters when reasoning precisely about test isolation.
Cricket analogy: A quick reference like this is like a scorecard's abbreviation key printed on the back page — you glance at it mid-match to instantly recall what 'LBW' or 'c&b' means without breaking your focus on the game.
The Testing Pyramid at a Glance
Unit tests verify a single function or class in isolation, run in milliseconds, and should make up the bulk of a suite. Integration tests verify that two or more real components work together correctly (e.g., a service talking to a real test database), running slower and in smaller numbers. End-to-end tests drive the full system through its real interface (often a browser via Playwright or Cypress), are the slowest and most brittle, and should be reserved for a small number of critical user journeys like checkout or login.
Cricket analogy: Unit, integration, and end-to-end tests map to net practice, a warm-up match, and the actual tournament final — increasing realism and stakes, decreasing how often you can afford to run them.
Arrange-Act-Assert (AAA)
AAA structures any individual test into three clearly separated blocks: Arrange sets up the inputs and preconditions, Act invokes the single behavior under test, and Assert checks the outcome. Keeping these blocks visually separated (often with a blank line) makes tests scannable at a glance and reveals when a test is doing too much — if the Act block has more than one meaningful call, the test is probably testing more than one behavior and should likely be split.
Cricket analogy: AAA is like a delivery breakdown into run-up, release, and result — the bowler's approach (arrange), the ball leaving the hand (act), and the umpire's decision (assert) are always distinct, sequential phases.
test('applies free shipping over $50', () => {
// Arrange
const cart = new Cart();
cart.addItem({ price: 60, qty: 1 });
// Act
const shippingCost = cart.calculateShipping();
// Assert
expect(shippingCost).toBe(0);
});Test Doubles: Mock, Stub, Fake, Spy
These four terms are often used interchangeably but mean distinct things. A stub returns canned answers to calls made during the test (e.g., a stubbed API client that always returns a fixed JSON response). A mock is a stub that also verifies interactions happened as expected (e.g., asserting 'sendEmail was called exactly once with this argument'). A fake is a working but simplified implementation (e.g., an in-memory database standing in for a real one). A spy wraps a real implementation while recording calls, letting you assert on usage without replacing behavior.
Cricket analogy: A stub is like a bowling machine set to always deliver the same line and length — predictable input, no real variation. A mock is like that machine paired with a sensor that confirms exactly six balls were bowled at the agreed speed. A fake is like a simplified indoor net pitch standing in for a real outdoor wicket. A spy is like a real bowler with a radar gun recording every delivery's speed without changing how they bowl.
When in doubt about terminology in conversation with teammates, precision matters less than consistency — agree on team-wide definitions once (e.g., in a README) so 'mock' means the same thing to everyone reviewing a PR.
Overusing mocks that assert on exact call arguments makes tests brittle to harmless refactors (e.g., reordering function arguments breaks the mock assertion even though behavior is unchanged). Prefer stubs/fakes for setup and reserve strict mock verification for interactions that are genuinely part of the contract, like 'an email must be sent exactly once.'
- The testing pyramid: many fast unit tests, fewer integration tests, very few slow end-to-end tests.
- AAA (Arrange-Act-Assert) structures each test into setup, the action under test, and the verification.
- A stub returns canned data; a mock also verifies interactions occurred as expected.
- A fake is a simplified working implementation (e.g., in-memory DB); a spy wraps real behavior while recording calls.
- If a test's Act block has more than one meaningful call, it's likely testing more than one behavior.
- Agree on team-wide terminology for test doubles to avoid confusion in code review.
- Overusing strict mock argument assertions makes tests brittle to harmless refactors.
Practice what you learned
1. In the testing pyramid, why should end-to-end tests be the smallest category?
2. What does the 'Act' block in the AAA pattern represent?
3. What is the key distinction between a stub and a mock?
4. What does a 'fake' test double typically refer to?
5. Why can overusing strict mock argument assertions make a test suite brittle?
Was this page helpful?
You May Also Like
Choosing a Testing Framework
How to evaluate and select a testing framework based on language fit, assertion style, runner speed, and team workflow.
Testing Interview Questions
Common technical interview questions on testing and TDD, with the reasoning behind strong answers.
TDD Case Study Walkthrough
A step-by-step worked example of building a small feature using the red-green-refactor TDD cycle.
Related Reading
Related Study Notes in Software Engineering
Browse all study notesMicroservices Study Notes
Software Architecture · 30 topics
Software EngineeringDesign Patterns Study Notes
Software Design · 30 topics
Software EngineeringSoftware Engineering Study Notes
Python · 40 topics
Software EngineeringGit & Version Control Study Notes
Bash · 40 topics
Software EngineeringSystem Design Study Notes
Architecture · 40 topics