@shaykec/bridge 0.4.24 → 0.4.26
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/journeys/ai-engineer.yaml +34 -0
- package/journeys/backend-developer.yaml +36 -0
- package/journeys/business-analyst.yaml +37 -0
- package/journeys/devops-engineer.yaml +37 -0
- package/journeys/engineering-manager.yaml +44 -0
- package/journeys/frontend-developer.yaml +41 -0
- package/journeys/fullstack-developer.yaml +49 -0
- package/journeys/mobile-developer.yaml +42 -0
- package/journeys/product-manager.yaml +35 -0
- package/journeys/qa-engineer.yaml +37 -0
- package/journeys/ux-designer.yaml +43 -0
- package/modules/README.md +52 -0
- package/modules/accessibility-fundamentals/content.md +126 -0
- package/modules/accessibility-fundamentals/exercises.md +88 -0
- package/modules/accessibility-fundamentals/module.yaml +43 -0
- package/modules/accessibility-fundamentals/quick-ref.md +71 -0
- package/modules/accessibility-fundamentals/quiz.md +100 -0
- package/modules/accessibility-fundamentals/resources.md +29 -0
- package/modules/accessibility-fundamentals/walkthrough.md +80 -0
- package/modules/adr-writing/content.md +121 -0
- package/modules/adr-writing/exercises.md +81 -0
- package/modules/adr-writing/module.yaml +41 -0
- package/modules/adr-writing/quick-ref.md +57 -0
- package/modules/adr-writing/quiz.md +73 -0
- package/modules/adr-writing/resources.md +29 -0
- package/modules/adr-writing/walkthrough.md +64 -0
- package/modules/ai-agents/content.md +120 -0
- package/modules/ai-agents/exercises.md +82 -0
- package/modules/ai-agents/module.yaml +42 -0
- package/modules/ai-agents/quick-ref.md +60 -0
- package/modules/ai-agents/quiz.md +103 -0
- package/modules/ai-agents/resources.md +30 -0
- package/modules/ai-agents/walkthrough.md +85 -0
- package/modules/ai-assisted-research/content.md +136 -0
- package/modules/ai-assisted-research/exercises.md +80 -0
- package/modules/ai-assisted-research/module.yaml +42 -0
- package/modules/ai-assisted-research/quick-ref.md +67 -0
- package/modules/ai-assisted-research/quiz.md +73 -0
- package/modules/ai-assisted-research/resources.md +33 -0
- package/modules/ai-assisted-research/walkthrough.md +85 -0
- package/modules/ai-pair-programming/content.md +105 -0
- package/modules/ai-pair-programming/exercises.md +98 -0
- package/modules/ai-pair-programming/module.yaml +39 -0
- package/modules/ai-pair-programming/quick-ref.md +58 -0
- package/modules/ai-pair-programming/quiz.md +73 -0
- package/modules/ai-pair-programming/resources.md +34 -0
- package/modules/ai-pair-programming/walkthrough.md +117 -0
- package/modules/ai-test-generation/content.md +125 -0
- package/modules/ai-test-generation/exercises.md +98 -0
- package/modules/ai-test-generation/module.yaml +39 -0
- package/modules/ai-test-generation/quick-ref.md +65 -0
- package/modules/ai-test-generation/quiz.md +74 -0
- package/modules/ai-test-generation/resources.md +41 -0
- package/modules/ai-test-generation/walkthrough.md +100 -0
- package/modules/api-design/content.md +189 -0
- package/modules/api-design/exercises.md +84 -0
- package/modules/api-design/game.yaml +113 -0
- package/modules/api-design/module.yaml +45 -0
- package/modules/api-design/quick-ref.md +73 -0
- package/modules/api-design/quiz.md +100 -0
- package/modules/api-design/resources.md +55 -0
- package/modules/api-design/walkthrough.md +88 -0
- package/modules/clean-code/content.md +136 -0
- package/modules/clean-code/exercises.md +137 -0
- package/modules/clean-code/game.yaml +172 -0
- package/modules/clean-code/module.yaml +44 -0
- package/modules/clean-code/quick-ref.md +44 -0
- package/modules/clean-code/quiz.md +105 -0
- package/modules/clean-code/resources.md +40 -0
- package/modules/clean-code/walkthrough.md +78 -0
- package/modules/clean-code/workshop.yaml +149 -0
- package/modules/code-review/content.md +130 -0
- package/modules/code-review/exercises.md +95 -0
- package/modules/code-review/game.yaml +83 -0
- package/modules/code-review/module.yaml +42 -0
- package/modules/code-review/quick-ref.md +77 -0
- package/modules/code-review/quiz.md +105 -0
- package/modules/code-review/resources.md +40 -0
- package/modules/code-review/walkthrough.md +106 -0
- package/modules/daily-workflow/content.md +81 -0
- package/modules/daily-workflow/exercises.md +50 -0
- package/modules/daily-workflow/module.yaml +33 -0
- package/modules/daily-workflow/quick-ref.md +37 -0
- package/modules/daily-workflow/quiz.md +65 -0
- package/modules/daily-workflow/resources.md +38 -0
- package/modules/daily-workflow/walkthrough.md +83 -0
- package/modules/debugging-systematically/content.md +139 -0
- package/modules/debugging-systematically/exercises.md +91 -0
- package/modules/debugging-systematically/module.yaml +46 -0
- package/modules/debugging-systematically/quick-ref.md +59 -0
- package/modules/debugging-systematically/quiz.md +105 -0
- package/modules/debugging-systematically/resources.md +42 -0
- package/modules/debugging-systematically/walkthrough.md +84 -0
- package/modules/debugging-systematically/workshop.yaml +127 -0
- package/modules/demo-test/content.md +68 -0
- package/modules/demo-test/exercises.md +28 -0
- package/modules/demo-test/game.yaml +171 -0
- package/modules/demo-test/module.yaml +41 -0
- package/modules/demo-test/quick-ref.md +54 -0
- package/modules/demo-test/quiz.md +74 -0
- package/modules/demo-test/resources.md +21 -0
- package/modules/demo-test/walkthrough.md +122 -0
- package/modules/demo-test/workshop.yaml +31 -0
- package/modules/design-critique/content.md +93 -0
- package/modules/design-critique/exercises.md +71 -0
- package/modules/design-critique/module.yaml +41 -0
- package/modules/design-critique/quick-ref.md +63 -0
- package/modules/design-critique/quiz.md +73 -0
- package/modules/design-critique/resources.md +27 -0
- package/modules/design-critique/walkthrough.md +68 -0
- package/modules/design-patterns/content.md +335 -0
- package/modules/design-patterns/exercises.md +82 -0
- package/modules/design-patterns/game.yaml +55 -0
- package/modules/design-patterns/module.yaml +45 -0
- package/modules/design-patterns/quick-ref.md +44 -0
- package/modules/design-patterns/quiz.md +101 -0
- package/modules/design-patterns/resources.md +40 -0
- package/modules/design-patterns/walkthrough.md +64 -0
- package/modules/exploratory-testing/content.md +133 -0
- package/modules/exploratory-testing/exercises.md +88 -0
- package/modules/exploratory-testing/module.yaml +41 -0
- package/modules/exploratory-testing/quick-ref.md +68 -0
- package/modules/exploratory-testing/quiz.md +75 -0
- package/modules/exploratory-testing/resources.md +39 -0
- package/modules/exploratory-testing/walkthrough.md +87 -0
- package/modules/git/content.md +128 -0
- package/modules/git/exercises.md +53 -0
- package/modules/git/game.yaml +190 -0
- package/modules/git/module.yaml +44 -0
- package/modules/git/quick-ref.md +67 -0
- package/modules/git/quiz.md +89 -0
- package/modules/git/resources.md +49 -0
- package/modules/git/walkthrough.md +92 -0
- package/modules/git/workshop.yaml +145 -0
- package/modules/hiring-interviews/content.md +130 -0
- package/modules/hiring-interviews/exercises.md +88 -0
- package/modules/hiring-interviews/module.yaml +41 -0
- package/modules/hiring-interviews/quick-ref.md +68 -0
- package/modules/hiring-interviews/quiz.md +73 -0
- package/modules/hiring-interviews/resources.md +36 -0
- package/modules/hiring-interviews/walkthrough.md +75 -0
- package/modules/hooks/content.md +97 -0
- package/modules/hooks/exercises.md +69 -0
- package/modules/hooks/module.yaml +39 -0
- package/modules/hooks/quick-ref.md +93 -0
- package/modules/hooks/quiz.md +81 -0
- package/modules/hooks/resources.md +34 -0
- package/modules/hooks/walkthrough.md +105 -0
- package/modules/hooks/workshop.yaml +64 -0
- package/modules/incident-response/content.md +124 -0
- package/modules/incident-response/exercises.md +82 -0
- package/modules/incident-response/game.yaml +132 -0
- package/modules/incident-response/module.yaml +45 -0
- package/modules/incident-response/quick-ref.md +53 -0
- package/modules/incident-response/quiz.md +103 -0
- package/modules/incident-response/resources.md +40 -0
- package/modules/incident-response/walkthrough.md +82 -0
- package/modules/llm-fundamentals/content.md +114 -0
- package/modules/llm-fundamentals/exercises.md +83 -0
- package/modules/llm-fundamentals/module.yaml +42 -0
- package/modules/llm-fundamentals/quick-ref.md +64 -0
- package/modules/llm-fundamentals/quiz.md +103 -0
- package/modules/llm-fundamentals/resources.md +30 -0
- package/modules/llm-fundamentals/walkthrough.md +91 -0
- package/modules/one-on-ones/content.md +133 -0
- package/modules/one-on-ones/exercises.md +81 -0
- package/modules/one-on-ones/module.yaml +44 -0
- package/modules/one-on-ones/quick-ref.md +67 -0
- package/modules/one-on-ones/quiz.md +73 -0
- package/modules/one-on-ones/resources.md +37 -0
- package/modules/one-on-ones/walkthrough.md +69 -0
- package/modules/package.json +9 -0
- package/modules/prioritization-frameworks/content.md +130 -0
- package/modules/prioritization-frameworks/exercises.md +93 -0
- package/modules/prioritization-frameworks/module.yaml +41 -0
- package/modules/prioritization-frameworks/quick-ref.md +77 -0
- package/modules/prioritization-frameworks/quiz.md +73 -0
- package/modules/prioritization-frameworks/resources.md +32 -0
- package/modules/prioritization-frameworks/walkthrough.md +69 -0
- package/modules/prompt-engineering/content.md +123 -0
- package/modules/prompt-engineering/exercises.md +82 -0
- package/modules/prompt-engineering/game.yaml +101 -0
- package/modules/prompt-engineering/module.yaml +45 -0
- package/modules/prompt-engineering/quick-ref.md +65 -0
- package/modules/prompt-engineering/quiz.md +105 -0
- package/modules/prompt-engineering/resources.md +36 -0
- package/modules/prompt-engineering/walkthrough.md +81 -0
- package/modules/rag-fundamentals/content.md +111 -0
- package/modules/rag-fundamentals/exercises.md +80 -0
- package/modules/rag-fundamentals/module.yaml +45 -0
- package/modules/rag-fundamentals/quick-ref.md +58 -0
- package/modules/rag-fundamentals/quiz.md +75 -0
- package/modules/rag-fundamentals/resources.md +34 -0
- package/modules/rag-fundamentals/walkthrough.md +75 -0
- package/modules/react-fundamentals/content.md +140 -0
- package/modules/react-fundamentals/exercises.md +81 -0
- package/modules/react-fundamentals/game.yaml +145 -0
- package/modules/react-fundamentals/module.yaml +45 -0
- package/modules/react-fundamentals/quick-ref.md +62 -0
- package/modules/react-fundamentals/quiz.md +106 -0
- package/modules/react-fundamentals/resources.md +42 -0
- package/modules/react-fundamentals/walkthrough.md +89 -0
- package/modules/react-fundamentals/workshop.yaml +112 -0
- package/modules/react-native-fundamentals/content.md +141 -0
- package/modules/react-native-fundamentals/exercises.md +79 -0
- package/modules/react-native-fundamentals/module.yaml +42 -0
- package/modules/react-native-fundamentals/quick-ref.md +60 -0
- package/modules/react-native-fundamentals/quiz.md +61 -0
- package/modules/react-native-fundamentals/resources.md +24 -0
- package/modules/react-native-fundamentals/walkthrough.md +84 -0
- package/modules/registry.yaml +1650 -0
- package/modules/risk-management/content.md +162 -0
- package/modules/risk-management/exercises.md +86 -0
- package/modules/risk-management/module.yaml +41 -0
- package/modules/risk-management/quick-ref.md +82 -0
- package/modules/risk-management/quiz.md +73 -0
- package/modules/risk-management/resources.md +40 -0
- package/modules/risk-management/walkthrough.md +67 -0
- package/modules/running-effective-standups/content.md +119 -0
- package/modules/running-effective-standups/exercises.md +79 -0
- package/modules/running-effective-standups/module.yaml +40 -0
- package/modules/running-effective-standups/quick-ref.md +61 -0
- package/modules/running-effective-standups/quiz.md +73 -0
- package/modules/running-effective-standups/resources.md +36 -0
- package/modules/running-effective-standups/walkthrough.md +76 -0
- package/modules/solid-principles/content.md +154 -0
- package/modules/solid-principles/exercises.md +107 -0
- package/modules/solid-principles/module.yaml +42 -0
- package/modules/solid-principles/quick-ref.md +50 -0
- package/modules/solid-principles/quiz.md +102 -0
- package/modules/solid-principles/resources.md +39 -0
- package/modules/solid-principles/walkthrough.md +84 -0
- package/modules/sprint-planning/content.md +142 -0
- package/modules/sprint-planning/exercises.md +79 -0
- package/modules/sprint-planning/game.yaml +84 -0
- package/modules/sprint-planning/module.yaml +44 -0
- package/modules/sprint-planning/quick-ref.md +76 -0
- package/modules/sprint-planning/quiz.md +102 -0
- package/modules/sprint-planning/resources.md +39 -0
- package/modules/sprint-planning/walkthrough.md +75 -0
- package/modules/sql-fundamentals/content.md +160 -0
- package/modules/sql-fundamentals/exercises.md +87 -0
- package/modules/sql-fundamentals/game.yaml +105 -0
- package/modules/sql-fundamentals/module.yaml +45 -0
- package/modules/sql-fundamentals/quick-ref.md +53 -0
- package/modules/sql-fundamentals/quiz.md +103 -0
- package/modules/sql-fundamentals/resources.md +42 -0
- package/modules/sql-fundamentals/walkthrough.md +92 -0
- package/modules/sql-fundamentals/workshop.yaml +109 -0
- package/modules/stakeholder-communication/content.md +186 -0
- package/modules/stakeholder-communication/exercises.md +87 -0
- package/modules/stakeholder-communication/module.yaml +38 -0
- package/modules/stakeholder-communication/quick-ref.md +89 -0
- package/modules/stakeholder-communication/quiz.md +73 -0
- package/modules/stakeholder-communication/resources.md +41 -0
- package/modules/stakeholder-communication/walkthrough.md +74 -0
- package/modules/system-design/content.md +149 -0
- package/modules/system-design/exercises.md +83 -0
- package/modules/system-design/game.yaml +95 -0
- package/modules/system-design/module.yaml +46 -0
- package/modules/system-design/quick-ref.md +59 -0
- package/modules/system-design/quiz.md +102 -0
- package/modules/system-design/resources.md +46 -0
- package/modules/system-design/walkthrough.md +90 -0
- package/modules/team-topologies/content.md +166 -0
- package/modules/team-topologies/exercises.md +85 -0
- package/modules/team-topologies/module.yaml +41 -0
- package/modules/team-topologies/quick-ref.md +61 -0
- package/modules/team-topologies/quiz.md +101 -0
- package/modules/team-topologies/resources.md +37 -0
- package/modules/team-topologies/walkthrough.md +76 -0
- package/modules/technical-debt/content.md +111 -0
- package/modules/technical-debt/exercises.md +92 -0
- package/modules/technical-debt/module.yaml +39 -0
- package/modules/technical-debt/quick-ref.md +60 -0
- package/modules/technical-debt/quiz.md +73 -0
- package/modules/technical-debt/resources.md +25 -0
- package/modules/technical-debt/walkthrough.md +94 -0
- package/modules/technical-mentoring/content.md +128 -0
- package/modules/technical-mentoring/exercises.md +84 -0
- package/modules/technical-mentoring/module.yaml +41 -0
- package/modules/technical-mentoring/quick-ref.md +74 -0
- package/modules/technical-mentoring/quiz.md +73 -0
- package/modules/technical-mentoring/resources.md +33 -0
- package/modules/technical-mentoring/walkthrough.md +65 -0
- package/modules/test-strategy/content.md +136 -0
- package/modules/test-strategy/exercises.md +84 -0
- package/modules/test-strategy/game.yaml +99 -0
- package/modules/test-strategy/module.yaml +45 -0
- package/modules/test-strategy/quick-ref.md +66 -0
- package/modules/test-strategy/quiz.md +99 -0
- package/modules/test-strategy/resources.md +60 -0
- package/modules/test-strategy/walkthrough.md +97 -0
- package/modules/test-strategy/workshop.yaml +96 -0
- package/modules/typescript-fundamentals/content.md +127 -0
- package/modules/typescript-fundamentals/exercises.md +79 -0
- package/modules/typescript-fundamentals/game.yaml +111 -0
- package/modules/typescript-fundamentals/module.yaml +45 -0
- package/modules/typescript-fundamentals/quick-ref.md +55 -0
- package/modules/typescript-fundamentals/quiz.md +104 -0
- package/modules/typescript-fundamentals/resources.md +42 -0
- package/modules/typescript-fundamentals/walkthrough.md +71 -0
- package/modules/typescript-fundamentals/workshop.yaml +146 -0
- package/modules/user-story-mapping/content.md +123 -0
- package/modules/user-story-mapping/exercises.md +87 -0
- package/modules/user-story-mapping/module.yaml +41 -0
- package/modules/user-story-mapping/quick-ref.md +64 -0
- package/modules/user-story-mapping/quiz.md +73 -0
- package/modules/user-story-mapping/resources.md +29 -0
- package/modules/user-story-mapping/walkthrough.md +86 -0
- package/modules/writing-prds/content.md +133 -0
- package/modules/writing-prds/exercises.md +93 -0
- package/modules/writing-prds/game.yaml +83 -0
- package/modules/writing-prds/module.yaml +44 -0
- package/modules/writing-prds/quick-ref.md +77 -0
- package/modules/writing-prds/quiz.md +103 -0
- package/modules/writing-prds/resources.md +30 -0
- package/modules/writing-prds/walkthrough.md +87 -0
- package/package.json +5 -3
- package/src/server.js +17 -7
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
# Test Strategy — Pyramids, Diamonds, and What to Test
|
|
2
|
+
|
|
3
|
+
<!-- hint:slides topic="Test strategy: test pyramid, what to test vs skip, test doubles, CI placement, and coverage tradeoffs" slides="5" -->
|
|
4
|
+
|
|
5
|
+
## Why Test?
|
|
6
|
+
|
|
7
|
+
Tests give you **confidence to change**. They document behavior, catch regressions, and make refactoring safe. Without tests, every change is a gamble.
|
|
8
|
+
|
|
9
|
+
## The Classic Test Pyramid
|
|
10
|
+
|
|
11
|
+
Martin Fowler popularized the **test pyramid**: many fast, cheap unit tests at the base; fewer integration tests in the middle; and few slow, expensive end-to-end (e2e) tests at the top.
|
|
12
|
+
|
|
13
|
+
```mermaid
|
|
14
|
+
flowchart TB
|
|
15
|
+
subgraph E2E_layer[E2E - few, slow]
|
|
16
|
+
E2E[E2E Tests]
|
|
17
|
+
end
|
|
18
|
+
subgraph INT_layer[Integration - some]
|
|
19
|
+
INT[Integration Tests]
|
|
20
|
+
end
|
|
21
|
+
subgraph UNIT_layer[Unit - many, fast]
|
|
22
|
+
UNIT[Unit Tests]
|
|
23
|
+
end
|
|
24
|
+
UNIT_layer --> INT_layer
|
|
25
|
+
INT_layer --> E2E_layer
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
```mermaid
|
|
29
|
+
flowchart TB
|
|
30
|
+
subgraph pyramid["Test Pyramid"]
|
|
31
|
+
E2E["E2E Tests\n(slow, few)\nFull user flows"]
|
|
32
|
+
INT["Integration Tests\n(medium)\nComponents + DB/API"]
|
|
33
|
+
UNIT["Unit Tests\n(fast, many)\nSingle functions/classes"]
|
|
34
|
+
end
|
|
35
|
+
UNIT --> INT
|
|
36
|
+
INT --> E2E
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### Layer Characteristics
|
|
40
|
+
|
|
41
|
+
| Layer | What it tests | Speed | Isolation | Count |
|
|
42
|
+
|-------|---------------|-------|-----------|-------|
|
|
43
|
+
| **Unit** | Single function or class in isolation | Fast (ms) | High — mocks/stubs | Many |
|
|
44
|
+
| **Integration** | Components working together (DB, API, services) | Medium (seconds) | Medium — real deps | Some |
|
|
45
|
+
| **E2E** | Full user journey (UI → backend) | Slow (minutes) | Low — real everything | Few |
|
|
46
|
+
|
|
47
|
+
```javascript
|
|
48
|
+
// Unit: pure function, no I/O
|
|
49
|
+
function add(a, b) { return a + b; }
|
|
50
|
+
// Test: expect(add(2, 3)).toBe(5);
|
|
51
|
+
|
|
52
|
+
// Integration: hits DB or API
|
|
53
|
+
async function getUser(id) {
|
|
54
|
+
const res = await db.query('SELECT * FROM users WHERE id = ?', [id]);
|
|
55
|
+
return res.rows[0];
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// E2E: browser clicks → server → DB → response
|
|
59
|
+
// Playwright/Cypress: click "Login", fill form, assert dashboard
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## The Testing Diamond (or Trophy)
|
|
63
|
+
|
|
64
|
+
Some teams invert the pyramid: more integration tests than unit tests. The **diamond** or **trophy** shape reflects that business logic often lives in integration layers. The idea: test what matters, where it matters.
|
|
65
|
+
|
|
66
|
+
```
|
|
67
|
+
/\
|
|
68
|
+
/ \ E2E (few)
|
|
69
|
+
/----\
|
|
70
|
+
/ \ Integration (many)
|
|
71
|
+
/--------\
|
|
72
|
+
/ \ Unit (some)
|
|
73
|
+
-------------
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## What to Test
|
|
77
|
+
|
|
78
|
+
| Focus | Examples |
|
|
79
|
+
|-------|----------|
|
|
80
|
+
| **Happy path** | User logs in with valid credentials → sees dashboard |
|
|
81
|
+
| **Edge cases** | Empty list, max length, boundary values |
|
|
82
|
+
| **Error paths** | Invalid input, network failure, permission denied |
|
|
83
|
+
| **Contracts** | API returns expected shape; component accepts valid props |
|
|
84
|
+
|
|
85
|
+
## What NOT to Test
|
|
86
|
+
|
|
87
|
+
- **Implementation details** — Don't assert on internal state that might change during refactoring.
|
|
88
|
+
- **Third-party code** — Trust libraries; mock them if needed.
|
|
89
|
+
- **Trivial code** — Getters/setters with no logic.
|
|
90
|
+
- **Everything** — Diminishing returns; prioritize risk.
|
|
91
|
+
|
|
92
|
+
## Test Doubles: Mocks, Stubs, Spies
|
|
93
|
+
|
|
94
|
+
| Type | Purpose |
|
|
95
|
+
|------|---------|
|
|
96
|
+
| **Stub** | Returns canned data; no verification |
|
|
97
|
+
| **Mock** | Verifies it was called (expectations) |
|
|
98
|
+
| **Spy** | Records calls; can assert after |
|
|
99
|
+
|
|
100
|
+
```javascript
|
|
101
|
+
// Stub: fake DB returns specific data
|
|
102
|
+
const stubDb = { query: () => ({ rows: [{ id: 1, name: 'Alice' }] }) };
|
|
103
|
+
|
|
104
|
+
// Mock: expect fetch to be called with specific URL
|
|
105
|
+
const mockFetch = vi.fn();
|
|
106
|
+
expect(mockFetch).toHaveBeenCalledWith('/api/users');
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## Code Coverage
|
|
110
|
+
|
|
111
|
+
Coverage tells you **what you didn't test**. It's useful for finding gaps, but **100% coverage is not a goal**. Aim for meaningful coverage of critical paths; avoid testing for coverage's sake.
|
|
112
|
+
|
|
113
|
+
## Testing in CI/CD
|
|
114
|
+
|
|
115
|
+
- Run unit tests on every commit (fast feedback).
|
|
116
|
+
- Run integration tests on push to main.
|
|
117
|
+
- Run e2e tests on release branches or nightly.
|
|
118
|
+
|
|
119
|
+
```mermaid
|
|
120
|
+
flowchart LR
|
|
121
|
+
A[Commit] --> B[Unit Tests]
|
|
122
|
+
B --> C[Integration Tests]
|
|
123
|
+
C --> D[E2E Tests]
|
|
124
|
+
D --> E[Deploy]
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
---
|
|
128
|
+
|
|
129
|
+
## Key Takeaways
|
|
130
|
+
|
|
131
|
+
1. **Pyramid**: Many unit, some integration, few e2e.
|
|
132
|
+
2. **Test what matters**: Happy path, edge cases, error paths.
|
|
133
|
+
3. **Don't test**: Implementation details, third-party code.
|
|
134
|
+
4. **Use doubles** when you need isolation or speed.
|
|
135
|
+
5. **Coverage** is a metric, not a goal.
|
|
136
|
+
6. **CI/CD**: Fast tests first; gate deploys on passing tests.
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# Test Strategy Exercises
|
|
2
|
+
|
|
3
|
+
## Exercise 1: Draw Your Pyramid
|
|
4
|
+
|
|
5
|
+
**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)
|
|
6
|
+
|
|
7
|
+
**Validation:**
|
|
8
|
+
- [ ] Unit tests focus on single functions/classes
|
|
9
|
+
- [ ] Integration tests involve at least 2 components or real I/O
|
|
10
|
+
- [ ] E2E tests cover a full user flow
|
|
11
|
+
- [ ] Counts follow pyramid (many unit, few e2e)
|
|
12
|
+
|
|
13
|
+
**Hints:**
|
|
14
|
+
1. Start with the main user flows — what's critical?
|
|
15
|
+
2. Unit = logic you can run in memory with no DB/network
|
|
16
|
+
3. Integration = DB, API, file system, message queues
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## Exercise 2: Happy Path, Edge Case, Error Path
|
|
21
|
+
|
|
22
|
+
**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.
|
|
23
|
+
|
|
24
|
+
**Validation:**
|
|
25
|
+
- [ ] Happy path: normal inputs, expected output
|
|
26
|
+
- [ ] Edge cases: e.g., divide by 1, divide 0 by something
|
|
27
|
+
- [ ] Error path: e.g., divide by 0 — what should happen?
|
|
28
|
+
|
|
29
|
+
**Hints:**
|
|
30
|
+
1. Edge = boundaries, empty, single item, max values
|
|
31
|
+
2. Error = invalid input, exceptional conditions
|
|
32
|
+
3. Consider: does divide(0, 5) return 0? Is that edge or happy?
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## Exercise 3: Stub vs Mock
|
|
37
|
+
|
|
38
|
+
**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.
|
|
39
|
+
|
|
40
|
+
**Validation:**
|
|
41
|
+
- [ ] Stub scenario: you only care about the return value / receipt
|
|
42
|
+
- [ ] Mock scenario: you need to verify charge was called with correct amount
|
|
43
|
+
- [ ] Explanation of when each is appropriate
|
|
44
|
+
|
|
45
|
+
**Hints:**
|
|
46
|
+
1. Stub = "fake the answer so the code under test can run"
|
|
47
|
+
2. Mock = "verify the collaborator was used correctly"
|
|
48
|
+
3. Would you trust the code if charge was never called?
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## Exercise 4: What NOT to Test
|
|
53
|
+
|
|
54
|
+
**Task:** Review this list. Which would you skip testing? Why?
|
|
55
|
+
- A React component that renders `{user.name}`
|
|
56
|
+
- A function that parses a query string into an object
|
|
57
|
+
- A wrapper that calls `axios.get(url)` and returns `response.data`
|
|
58
|
+
- A sorting function that orders items by date
|
|
59
|
+
|
|
60
|
+
**Validation:**
|
|
61
|
+
- [ ] Identifies thin wrappers / third-party usage as low value
|
|
62
|
+
- [ ] Identifies parsing/sorting as good candidates (logic)
|
|
63
|
+
- [ ] Can justify each decision
|
|
64
|
+
|
|
65
|
+
**Hints:**
|
|
66
|
+
1. Trivial = no branching, no logic
|
|
67
|
+
2. Third-party = you don't own it; maybe one smoke test
|
|
68
|
+
3. Business logic = always test
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
## Exercise 5: Coverage Trap
|
|
73
|
+
|
|
74
|
+
**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."
|
|
75
|
+
|
|
76
|
+
**Validation:**
|
|
77
|
+
- [ ] Meaningful = asserts behavior, not just "it didn't throw"
|
|
78
|
+
- [ ] Guideline about edge cases and error paths
|
|
79
|
+
- [ ] Guideline about refactoring — tests should catch regressions
|
|
80
|
+
|
|
81
|
+
**Hints:**
|
|
82
|
+
1. What would 95% coverage miss if assertions are shallow?
|
|
83
|
+
2. If you change behavior, would the test fail?
|
|
84
|
+
3. Coverage can be gamed; what can't be gamed?
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
games:
|
|
2
|
+
- type: classify
|
|
3
|
+
title: "Test Layer Classifier"
|
|
4
|
+
categories:
|
|
5
|
+
- name: "Unit Test"
|
|
6
|
+
color: "#58a6ff"
|
|
7
|
+
- name: "Integration Test"
|
|
8
|
+
color: "#3fb950"
|
|
9
|
+
- name: "E2E Test"
|
|
10
|
+
color: "#d29922"
|
|
11
|
+
items:
|
|
12
|
+
- text: "Tests a single function in isolation with dependencies mocked. Fast, many tests."
|
|
13
|
+
category: "Unit Test"
|
|
14
|
+
- text: "Spins up a real database, hits real endpoints, verifies service + DB together."
|
|
15
|
+
category: "Integration Test"
|
|
16
|
+
- text: "Launches the full app in a browser, simulates user clicks, checks rendered UI."
|
|
17
|
+
category: "E2E Test"
|
|
18
|
+
- text: "Tests that UserRepository.save() correctly persists to the DB with a test DB."
|
|
19
|
+
category: "Integration Test"
|
|
20
|
+
- text: "Tests formatPrice(99.99) returns '$99.99' with no external deps."
|
|
21
|
+
category: "Unit Test"
|
|
22
|
+
- text: "Uses Playwright to log in, add item to cart, and complete checkout flow."
|
|
23
|
+
category: "E2E Test"
|
|
24
|
+
- text: "Mocks PaymentService; tests OrderService.applyDiscount() with fake payment client."
|
|
25
|
+
category: "Unit Test"
|
|
26
|
+
- text: "Starts API server + DB, sends HTTP request, asserts response and DB state."
|
|
27
|
+
category: "Integration Test"
|
|
28
|
+
- text: "Tests a React component with React Testing Library; mocks child components."
|
|
29
|
+
category: "Unit Test"
|
|
30
|
+
- text: "Runs in a real browser, tests full signup → email verify → first login flow."
|
|
31
|
+
category: "E2E Test"
|
|
32
|
+
|
|
33
|
+
- type: speed-round
|
|
34
|
+
title: "Test Double Sprint"
|
|
35
|
+
rounds:
|
|
36
|
+
- question: "You need to verify that sendEmail() was called with the user's address. Which double?"
|
|
37
|
+
options:
|
|
38
|
+
- "Stub"
|
|
39
|
+
- "Mock"
|
|
40
|
+
- "Fake"
|
|
41
|
+
- "Dummy"
|
|
42
|
+
answer: 1
|
|
43
|
+
timeLimit: 16
|
|
44
|
+
- question: "You need a simple object to satisfy a parameter but never use it. Which?"
|
|
45
|
+
options:
|
|
46
|
+
- "Mock"
|
|
47
|
+
- "Stub"
|
|
48
|
+
- "Spy"
|
|
49
|
+
- "Dummy"
|
|
50
|
+
answer: 3
|
|
51
|
+
timeLimit: 16
|
|
52
|
+
- question: "You need to return a fixed response without hitting the real API. Which?"
|
|
53
|
+
options:
|
|
54
|
+
- "Mock"
|
|
55
|
+
- "Stub"
|
|
56
|
+
- "Spy"
|
|
57
|
+
- "Dummy"
|
|
58
|
+
answer: 1
|
|
59
|
+
timeLimit: 16
|
|
60
|
+
- question: "You want to record calls to a method for later assertion. Which?"
|
|
61
|
+
options:
|
|
62
|
+
- "Stub"
|
|
63
|
+
- "Spy"
|
|
64
|
+
- "Fake"
|
|
65
|
+
- "Dummy"
|
|
66
|
+
answer: 1
|
|
67
|
+
timeLimit: 16
|
|
68
|
+
- question: "You need a working in-memory implementation instead of real DB. Which?"
|
|
69
|
+
options:
|
|
70
|
+
- "Mock"
|
|
71
|
+
- "Stub"
|
|
72
|
+
- "Fake"
|
|
73
|
+
- "Dummy"
|
|
74
|
+
answer: 2
|
|
75
|
+
timeLimit: 16
|
|
76
|
+
- question: "You need to assert that a method was called exactly once. Which double?"
|
|
77
|
+
options:
|
|
78
|
+
- "Stub"
|
|
79
|
+
- "Mock"
|
|
80
|
+
- "Fake"
|
|
81
|
+
- "Dummy"
|
|
82
|
+
answer: 1
|
|
83
|
+
timeLimit: 16
|
|
84
|
+
- question: "You need to replace a slow service with a simple return value. Which?"
|
|
85
|
+
options:
|
|
86
|
+
- "Mock"
|
|
87
|
+
- "Stub"
|
|
88
|
+
- "Spy"
|
|
89
|
+
- "Dummy"
|
|
90
|
+
answer: 1
|
|
91
|
+
timeLimit: 15
|
|
92
|
+
- question: "You wrap a real object to record its calls. Which?"
|
|
93
|
+
options:
|
|
94
|
+
- "Stub"
|
|
95
|
+
- "Mock"
|
|
96
|
+
- "Spy"
|
|
97
|
+
- "Dummy"
|
|
98
|
+
answer: 2
|
|
99
|
+
timeLimit: 16
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
slug: test-strategy
|
|
2
|
+
title: "Test Strategy — Pyramids, Diamonds, and What to Test"
|
|
3
|
+
version: 1.0.0
|
|
4
|
+
description: "Design a balanced test strategy: the test pyramid, diamonds, and what to test at each layer."
|
|
5
|
+
category: quality-assurance
|
|
6
|
+
tags: [testing, test-strategy, test-pyramid, unit-tests, integration-tests, e2e]
|
|
7
|
+
difficulty: beginner
|
|
8
|
+
|
|
9
|
+
xp:
|
|
10
|
+
read: 10
|
|
11
|
+
walkthrough: 30
|
|
12
|
+
exercise: 20
|
|
13
|
+
quiz: 15
|
|
14
|
+
quiz-perfect-bonus: 10
|
|
15
|
+
game: 20
|
|
16
|
+
game-perfect-bonus: 10
|
|
17
|
+
|
|
18
|
+
time:
|
|
19
|
+
quick: 5
|
|
20
|
+
read: 15
|
|
21
|
+
guided: 45
|
|
22
|
+
|
|
23
|
+
prerequisites: []
|
|
24
|
+
related: [exploratory-testing, debugging-systematically]
|
|
25
|
+
|
|
26
|
+
triggers:
|
|
27
|
+
- "What should I test?"
|
|
28
|
+
- "What is the test pyramid?"
|
|
29
|
+
- "How many unit tests do I need?"
|
|
30
|
+
- "What's the difference between unit, integration, and e2e tests?"
|
|
31
|
+
|
|
32
|
+
visuals:
|
|
33
|
+
diagrams: [diagram-mermaid, diagram-flow]
|
|
34
|
+
quiz-types: [quiz-drag-order, quiz-matching]
|
|
35
|
+
game-types: [classify, speed-round]
|
|
36
|
+
playground: javascript
|
|
37
|
+
slides: true
|
|
38
|
+
|
|
39
|
+
sources:
|
|
40
|
+
- url: "https://martinfowler.com/articles/practical-test-pyramid.html"
|
|
41
|
+
label: "The Practical Test Pyramid (Martin Fowler)"
|
|
42
|
+
type: docs
|
|
43
|
+
- url: "https://www.amazon.com/Test-Driven-Development-Kent-Beck/dp/0321146530"
|
|
44
|
+
label: "TDD by Kent Beck (book)"
|
|
45
|
+
type: book
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# Test Strategy — Quick Reference
|
|
2
|
+
|
|
3
|
+
## Test Pyramid
|
|
4
|
+
|
|
5
|
+
| Layer | What It Tests | Speed | Count |
|
|
6
|
+
|-------|---------------|-------|-------|
|
|
7
|
+
| **Unit** | Single function/class in isolation | Fast (ms) | Many |
|
|
8
|
+
| **Integration** | Components + DB/API/services | Medium | Some |
|
|
9
|
+
| **E2E** | Full user journey (UI → backend) | Slow (min) | Few |
|
|
10
|
+
|
|
11
|
+
**Rule:** Many unit, some integration, few e2e.
|
|
12
|
+
|
|
13
|
+
## What to Test
|
|
14
|
+
|
|
15
|
+
| Focus | Examples |
|
|
16
|
+
|-------|----------|
|
|
17
|
+
| **Happy path** | Valid input → expected output |
|
|
18
|
+
| **Edge cases** | Empty list, boundary values, max length |
|
|
19
|
+
| **Error paths** | Invalid input, network failure, permission denied |
|
|
20
|
+
| **Contracts** | API shape, component props |
|
|
21
|
+
|
|
22
|
+
## What NOT to Test
|
|
23
|
+
|
|
24
|
+
- **Implementation details** — Internal state, hook call counts
|
|
25
|
+
- **Third-party code** — Trust libraries; mock if needed
|
|
26
|
+
- **Trivial code** — Getters/setters with no logic
|
|
27
|
+
- **Everything** — Prioritize risk; diminishing returns
|
|
28
|
+
|
|
29
|
+
## Test Doubles
|
|
30
|
+
|
|
31
|
+
| Type | Purpose |
|
|
32
|
+
|------|---------|
|
|
33
|
+
| **Stub** | Returns canned data; no verification |
|
|
34
|
+
| **Mock** | Verifies it was called (expectations) |
|
|
35
|
+
| **Spy** | Records calls; assert after |
|
|
36
|
+
|
|
37
|
+
**When stub:** You only need a fake response.
|
|
38
|
+
**When mock:** You need to verify the collaborator was used correctly.
|
|
39
|
+
|
|
40
|
+
## CI/CD Order
|
|
41
|
+
|
|
42
|
+
```
|
|
43
|
+
Commit → Unit (fast) → Integration → E2E → Deploy
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
- Unit + integration: every PR
|
|
47
|
+
- E2E: merge to main or nightly (optional per-PR)
|
|
48
|
+
|
|
49
|
+
## Coverage
|
|
50
|
+
|
|
51
|
+
- **Use:** Find gaps in critical paths
|
|
52
|
+
- **Don't:** Aim for 100%; avoid testing for coverage's sake
|
|
53
|
+
- **Meaningful coverage:** Assert behavior, not just "didn't throw"
|
|
54
|
+
|
|
55
|
+
## Diamond/Trophy Shape
|
|
56
|
+
|
|
57
|
+
Some teams invert the pyramid: more integration than unit. Use when business logic lives in integration layers. Test what matters, where it matters.
|
|
58
|
+
|
|
59
|
+
## Quick Checklist
|
|
60
|
+
|
|
61
|
+
- [ ] Unit tests for logic, validation, edge cases
|
|
62
|
+
- [ ] Integration tests for DB, API, services
|
|
63
|
+
- [ ] E2E for critical user flows (few)
|
|
64
|
+
- [ ] Stub/mock external dependencies in unit tests
|
|
65
|
+
- [ ] Avoid asserting on implementation details
|
|
66
|
+
- [ ] Run fast tests first in CI
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# Test Strategy Quiz
|
|
2
|
+
|
|
3
|
+
## Question 1
|
|
4
|
+
|
|
5
|
+
In the classic test pyramid, which layer should have the most tests?
|
|
6
|
+
|
|
7
|
+
A) Integration tests
|
|
8
|
+
B) End-to-end tests
|
|
9
|
+
C) Unit tests
|
|
10
|
+
D) All layers should have roughly equal numbers
|
|
11
|
+
|
|
12
|
+
<!-- ANSWER: C -->
|
|
13
|
+
<!-- EXPLANATION: The test pyramid recommends many fast, cheap unit tests at the base; fewer integration tests in the middle; and few slow e2e tests at the top. Unit tests run quickly and give fast feedback. -->
|
|
14
|
+
|
|
15
|
+
## Question 2
|
|
16
|
+
|
|
17
|
+
What is the main difference between a stub and a mock?
|
|
18
|
+
|
|
19
|
+
A) Stubs are faster; mocks are slower
|
|
20
|
+
B) A stub returns canned data; a mock verifies it was called with expectations
|
|
21
|
+
C) Stubs are for unit tests; mocks are for integration tests
|
|
22
|
+
D) There is no meaningful difference
|
|
23
|
+
|
|
24
|
+
<!-- ANSWER: B -->
|
|
25
|
+
<!-- EXPLANATION: A stub provides fake responses so the code under test can run—you don't verify how it was used. A mock lets you assert that it was called with specific arguments. Stubs fake; mocks verify. -->
|
|
26
|
+
|
|
27
|
+
## Question 3
|
|
28
|
+
|
|
29
|
+
Which of these is generally NOT recommended to test?
|
|
30
|
+
|
|
31
|
+
A) Business logic that computes tax based on state and subtotal
|
|
32
|
+
B) A thin wrapper that calls axios.get and returns response.data
|
|
33
|
+
C) Edge cases (empty list, boundary values)
|
|
34
|
+
D) Error paths (invalid input, network failure)
|
|
35
|
+
|
|
36
|
+
<!-- ANSWER: B -->
|
|
37
|
+
<!-- EXPLANATION: Thin wrappers over third-party code add little value to test—you're mostly testing the library. Business logic, edge cases, and error paths are high-value targets. You might add one smoke test for the wrapper. -->
|
|
38
|
+
|
|
39
|
+
## Question 4
|
|
40
|
+
|
|
41
|
+
When might a team use a "diamond" or "trophy" test shape instead of the classic pyramid?
|
|
42
|
+
|
|
43
|
+
A) When they want fewer unit tests
|
|
44
|
+
B) When business logic lives in integration layers and they test what matters where it matters
|
|
45
|
+
C) When e2e tests are faster than unit tests
|
|
46
|
+
D) When they have no integration tests
|
|
47
|
+
|
|
48
|
+
<!-- ANSWER: B -->
|
|
49
|
+
<!-- EXPLANATION: The diamond/trophy inverts the pyramid: more integration tests than unit tests. Teams use it when critical logic lives in components working together (DB, API, services). The principle: test what matters, where it matters. -->
|
|
50
|
+
|
|
51
|
+
## Question 5
|
|
52
|
+
|
|
53
|
+
Why might you run e2e tests only on merge to main, not on every PR?
|
|
54
|
+
|
|
55
|
+
A) E2E tests are less important than unit tests
|
|
56
|
+
B) E2E tests are slow and expensive; unit + integration on every PR gives fast feedback; e2e catches integration issues less frequently
|
|
57
|
+
C) E2E tests require manual approval
|
|
58
|
+
D) E2E tests cannot run in CI
|
|
59
|
+
|
|
60
|
+
<!-- ANSWER: B -->
|
|
61
|
+
<!-- EXPLANATION: E2E tests are valuable but slow. Running them on every PR increases feedback time. Many teams run unit + integration on every commit/PR for fast feedback, and run e2e on merge to main or nightly to balance speed and confidence. -->
|
|
62
|
+
|
|
63
|
+
## Question 6
|
|
64
|
+
|
|
65
|
+
Which assertion is most likely testing implementation details rather than behavior?
|
|
66
|
+
|
|
67
|
+
A) Assert that the user's name appears on the screen after login
|
|
68
|
+
B) Assert that the API was called with the correct parameters
|
|
69
|
+
C) Assert that useEffect was called exactly twice
|
|
70
|
+
D) Assert that the response status is 200
|
|
71
|
+
|
|
72
|
+
<!-- ANSWER: C -->
|
|
73
|
+
<!-- EXPLANATION: useEffect count is an implementation detail—if you refactor to a different hook or pattern, the test breaks even though user-visible behavior is unchanged. Asserting rendered output, API calls, or response status tests behavior. -->
|
|
74
|
+
|
|
75
|
+
## Question 7
|
|
76
|
+
|
|
77
|
+
<!-- VISUAL: drag-order -->
|
|
78
|
+
|
|
79
|
+
Put these test pyramid layers in order from base (most tests) to top (fewest tests):
|
|
80
|
+
|
|
81
|
+
A) Integration tests
|
|
82
|
+
B) Unit tests
|
|
83
|
+
C) End-to-end tests
|
|
84
|
+
|
|
85
|
+
<!-- ANSWER: B,A,C -->
|
|
86
|
+
<!-- EXPLANATION: The pyramid has many unit tests at the base (B), fewer integration tests in the middle (A), and few e2e tests at the top (C). -->
|
|
87
|
+
|
|
88
|
+
## Question 8
|
|
89
|
+
|
|
90
|
+
<!-- VISUAL: matching -->
|
|
91
|
+
|
|
92
|
+
Match each test type to its primary purpose:
|
|
93
|
+
|
|
94
|
+
A) Unit test → 1) Verify the full system works together (UI + backend + DB)
|
|
95
|
+
B) Integration test → 2) Verify a single function or class in isolation
|
|
96
|
+
C) E2E test → 3) Verify components work together (API + DB, or module + service)
|
|
97
|
+
|
|
98
|
+
<!-- ANSWER: A2,B3,C1 -->
|
|
99
|
+
<!-- EXPLANATION: Unit tests isolate small units (2). Integration tests verify component interaction (3). E2E tests exercise the full stack (1). -->
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# Test Strategy — Resources
|
|
2
|
+
|
|
3
|
+
## Core Reading
|
|
4
|
+
|
|
5
|
+
- [The Practical Test Pyramid](https://martinfowler.com/articles/practical-test-pyramid.html) — Martin Fowler. The definitive article: pyramid, trade-offs, and practical guidance.
|
|
6
|
+
- [Test Pyramid](https://martinfowler.com/bliki/TestPyramid.html) — Martin Fowler. Original bliki entry.
|
|
7
|
+
- [The Testing Trophy and Testing Classifications](https://kentcdodds.com/blog/the-testing-trophy-and-testing-classifications) — Kent C. Dodds. Diamond/trophy alternative to the pyramid.
|
|
8
|
+
|
|
9
|
+
## Books
|
|
10
|
+
|
|
11
|
+
- **Test Driven Development: By Example** by Kent Beck — TDD fundamentals: red-green-refactor, writing tests first.
|
|
12
|
+
- **Growing Object-Oriented Software, Guided by Tests** by Steve Freeman & Nat Pryce — Test-first design and mocking strategies.
|
|
13
|
+
|
|
14
|
+
## Testing Frameworks
|
|
15
|
+
|
|
16
|
+
- [Jest](https://jestjs.io/) — JavaScript unit testing. Fast, snapshot support, built-in mocks.
|
|
17
|
+
- [Vitest](https://vitest.dev/) — Vite-native test runner. Jest-compatible API, ESM, fast.
|
|
18
|
+
- [Playwright](https://playwright.dev/) — Cross-browser e2e testing. Reliable, modern API.
|
|
19
|
+
- [Cypress](https://www.cypress.io/) — E2E testing for the web. Great DX, time-travel debugging.
|
|
20
|
+
|
|
21
|
+
## Articles
|
|
22
|
+
|
|
23
|
+
- [What to Test](https://kentcdodds.com/blog/what-to-test) — Kent C. Dodds. Focus on implementation details vs behavior.
|
|
24
|
+
- [Unit Testing Best Practices](https://docs.microsoft.com/en-us/dotnet/core/testing/unit-testing-best-practices) — Microsoft. Naming, structure, what to mock.
|
|
25
|
+
- [Test Double Patterns](https://martinfowler.com/bliki/TestDouble.html) — Martin Fowler. Stub, mock, spy, fake, dummy.
|
|
26
|
+
|
|
27
|
+
## Videos
|
|
28
|
+
|
|
29
|
+
- [The Test Pyramid](https://www.youtube.com/watch?v=o0dS02sE_2c) — Martin Fowler (conference talk). Rationale and real-world use.
|
|
30
|
+
- [Rethinking the Test Pyramid](https://www.youtube.com/watch?v=z2q5_y-4qy0) — Google Testing Blog. Alternative shapes and when they fit.
|
|
31
|
+
- [Jest Tutorial](https://www.youtube.com/watch?v=FgnxcUQ5xho) — Academind. Getting started with Jest.
|
|
32
|
+
|
|
33
|
+
## Tools
|
|
34
|
+
|
|
35
|
+
- [Testing Library](https://testing-library.com/) — Test components from the user's perspective. React, Vue, DOM.
|
|
36
|
+
- [MSW (Mock Service Worker)](https://mswjs.io/) — Mock API at the network level. No changes to app code.
|
|
37
|
+
- [Sinon](https://sinonjs.org/) — Standalone mocks, stubs, spies for JavaScript.
|
|
38
|
+
|
|
39
|
+
## CI/CD
|
|
40
|
+
|
|
41
|
+
- [GitHub Actions — Test workflow](https://docs.github.com/en/actions/automating-builds-and-tests) — Run tests on push/PR.
|
|
42
|
+
- [Vitest — CI Configuration](https://vitest.dev/guide/ci.html) — Configuring Vitest for CI.
|
|
43
|
+
- [Playwright — CI](https://playwright.dev/docs/ci) — Running Playwright in GitHub Actions, etc.
|
|
44
|
+
|
|
45
|
+
## Podcasts
|
|
46
|
+
|
|
47
|
+
- [Test & Code](https://testandcode.com/) — Brian Okken. Episodes on testing strategies, TDD, and pytest patterns.
|
|
48
|
+
- [Software Engineering Daily — Testing](https://softwareengineeringdaily.com/?s=testing) — Deep dives on testing at scale, flaky tests, and CI pipelines.
|
|
49
|
+
- [JS Party — Testing Episodes](https://changelog.com/jsparty) — Panel discussions on JavaScript testing tools and strategies.
|
|
50
|
+
|
|
51
|
+
## Interactive and Visual
|
|
52
|
+
|
|
53
|
+
- [Testing Playground](https://testing-playground.com/) — Find the right Testing Library query for any DOM element visually.
|
|
54
|
+
- [Playwright Trace Viewer](https://playwright.dev/docs/trace-viewer-intro) — Replay test execution with screenshots, DOM snapshots, and network at each step.
|
|
55
|
+
- [Vitest UI](https://vitest.dev/guide/ui.html) — Visual test runner dashboard for browsing and debugging test results.
|
|
56
|
+
|
|
57
|
+
## Courses
|
|
58
|
+
|
|
59
|
+
- [Testing JavaScript (Kent C. Dodds)](https://testingjavascript.com/) — Comprehensive course: static analysis through E2E, with real-world projects.
|
|
60
|
+
- [freeCodeCamp — Quality Assurance](https://www.freecodecamp.org/learn/quality-assurance/) — Free certification covering unit testing, functional testing, and Chai assertions.
|