# Test Strategy Exercises

## Exercise 1: Draw Your Pyramid

**Task:** Pick a feature in a project you know (or a hypothetical one). Draw a test pyramid with 3 layers. For each layer, list 2–3 example tests. Estimate: how many of each? (e.g., 20 unit, 5 integration, 2 e2e)

**Validation:**
- [ ] Unit tests focus on single functions/classes
- [ ] Integration tests involve at least 2 components or real I/O
- [ ] E2E tests cover a full user flow
- [ ] Counts follow pyramid (many unit, few e2e)

**Hints:**
1. Start with the main user flows — what's critical?
2. Unit = logic you can run in memory with no DB/network
3. Integration = DB, API, file system, message queues

---

## Exercise 2: Happy Path, Edge Case, Error Path

**Task:** For a function `divide(a, b)` that returns `a / b`, write test case descriptions (not code) for: (a) happy path, (b) 2 edge cases, (c) 1 error path.

**Validation:**
- [ ] Happy path: normal inputs, expected output
- [ ] Edge cases: e.g., divide by 1, divide 0 by something
- [ ] Error path: e.g., divide by 0 — what should happen?

**Hints:**
1. Edge = boundaries, empty, single item, max values
2. Error = invalid input, exceptional conditions
3. Consider: does divide(0, 5) return 0? Is that edge or happy?

---

## Exercise 3: Stub vs Mock

**Task:** You're testing `checkout(cart, paymentService)`. The function calls `paymentService.charge(total)` and returns a receipt. Write two test scenarios in plain English: one where a stub is enough, one where you need a mock.

**Validation:**
- [ ] Stub scenario: you only care about the return value / receipt
- [ ] Mock scenario: you need to verify charge was called with correct amount
- [ ] Explanation of when each is appropriate

**Hints:**
1. Stub = "fake the answer so the code under test can run"
2. Mock = "verify the collaborator was used correctly"
3. Would you trust the code if charge was never called?

---

## Exercise 4: What NOT to Test

**Task:** Review this list. Which would you skip testing? Why?
- A React component that renders `{user.name}`
- A function that parses a query string into an object
- A wrapper that calls `axios.get(url)` and returns `response.data`
- A sorting function that orders items by date

**Validation:**
- [ ] Identifies thin wrappers / third-party usage as low value
- [ ] Identifies parsing/sorting as good candidates (logic)
- [ ] Can justify each decision

**Hints:**
1. Trivial = no branching, no logic
2. Third-party = you don't own it; maybe one smoke test
3. Business logic = always test

---

## Exercise 5: Coverage Trap

**Task:** A team boasts 95% line coverage. You discover their tests mostly do `expect(fn()).toBeDefined()` and rarely assert on actual behavior. Write 3 guidelines for "meaningful" coverage vs "coverage for its own sake."

**Validation:**
- [ ] Meaningful = asserts behavior, not just "it didn't throw"
- [ ] Guideline about edge cases and error paths
- [ ] Guideline about refactoring — tests should catch regressions

**Hints:**
1. What would 95% coverage miss if assertions are shallow?
2. If you change behavior, would the test fail?
3. Coverage can be gamed; what can't be gamed?
