@shaykec/bridge 0.4.25 → 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 +1 -1
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# AI-Assisted Test Generation Exercises
|
|
2
|
+
|
|
3
|
+
## Exercise 1: Write a Test Generation Prompt
|
|
4
|
+
|
|
5
|
+
**Task:** For this function, write a prompt you'd use to generate unit tests. Include: framework (Vitest), desired cases, and any style preferences.
|
|
6
|
+
|
|
7
|
+
```javascript
|
|
8
|
+
function slugify(text) {
|
|
9
|
+
return String(text)
|
|
10
|
+
.toLowerCase()
|
|
11
|
+
.trim()
|
|
12
|
+
.replace(/\s+/g, '-')
|
|
13
|
+
.replace(/[^a-z0-9-]/g, '');
|
|
14
|
+
}
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
**Validation:**
|
|
18
|
+
- [ ] Prompt includes the function (or clear reference)
|
|
19
|
+
- [ ] Framework specified
|
|
20
|
+
- [ ] At least 3 case types (e.g., happy, empty, special chars)
|
|
21
|
+
- [ ] Prompt is specific enough to get usable output
|
|
22
|
+
|
|
23
|
+
**Hints:**
|
|
24
|
+
1. What happens with "Hello World", "", "UPPERCASE", "a—b"?
|
|
25
|
+
2. Specify assert style: toBe, toEqual, toMatch
|
|
26
|
+
3. Include "trim and replace" behavior in the prompt
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## Exercise 2: Critique and Fix a Generated Test
|
|
31
|
+
|
|
32
|
+
**Task:** This test was AI-generated. Identify 2 problems and fix them.
|
|
33
|
+
|
|
34
|
+
```javascript
|
|
35
|
+
test('fetchUser works', async () => {
|
|
36
|
+
const result = await fetchUser(1);
|
|
37
|
+
expect(result).toBeTruthy();
|
|
38
|
+
});
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
**Validation:**
|
|
42
|
+
- [ ] Identifies shallow assertion (toBeTruthy)
|
|
43
|
+
- [ ] Identifies missing mock/setup if fetchUser hits network
|
|
44
|
+
- [ ] Proposes concrete improvements (e.g., expect(result.name).toBe('Alice'))
|
|
45
|
+
|
|
46
|
+
**Hints:**
|
|
47
|
+
1. What does toBeTruthy actually verify?
|
|
48
|
+
2. Does fetchUser need a mock? What would happen without it?
|
|
49
|
+
3. What would a strong assertion look like?
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## Exercise 3: Generate and Review
|
|
54
|
+
|
|
55
|
+
**Task:** Use Claude (or another AI) to generate tests for `slugify` from Exercise 1. Run them. Then review using the checklist: assertions verify behavior? Edge cases covered? Tests independent? List 2 improvements you'd make.
|
|
56
|
+
|
|
57
|
+
**Validation:**
|
|
58
|
+
- [ ] Tests were generated and run
|
|
59
|
+
- [ ] At least one improvement identified
|
|
60
|
+
- [ ] Improvement is actionable (specific change, not vague)
|
|
61
|
+
|
|
62
|
+
**Hints:**
|
|
63
|
+
1. Try the prompt you wrote in Exercise 1
|
|
64
|
+
2. Run with `npx vitest run` or your project's test command
|
|
65
|
+
3. Look for toBeDefined, toBeTruthy, or missing edge cases
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## Exercise 4: AI for Integration Test Setup
|
|
70
|
+
|
|
71
|
+
**Task:** You have an API endpoint `POST /users` that creates a user. Writing integration tests requires: DB setup, request body, and assertions. Write a prompt that asks AI to generate one integration test, including setup and teardown. Specify your stack (e.g., Node, Express, Jest, supertest).
|
|
72
|
+
|
|
73
|
+
**Validation:**
|
|
74
|
+
- [ ] Prompt specifies stack and tools
|
|
75
|
+
- [ ] Asks for setup (DB, server) and teardown
|
|
76
|
+
- [ ] Asks for clear assertion (status, body shape)
|
|
77
|
+
- [ ] Understands AI may need refinement—integration is complex
|
|
78
|
+
|
|
79
|
+
**Hints:**
|
|
80
|
+
1. "Generate integration test for POST /users with Jest and supertest"
|
|
81
|
+
2. Include: how to start/stop server, reset DB
|
|
82
|
+
3. Ask for status 201 and body containing id, name, email
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
## Exercise 5: Build a Prompt Template
|
|
87
|
+
|
|
88
|
+
**Task:** Create a reusable prompt template for unit test generation. Use placeholders like [FUNCTION], [FRAMEWORK], [CASES]. Write 2 example fills (different functions) showing how you'd use it.
|
|
89
|
+
|
|
90
|
+
**Validation:**
|
|
91
|
+
- [ ] Template has clear placeholders
|
|
92
|
+
- [ ] Template includes context that improves output (framework, style, cases)
|
|
93
|
+
- [ ] Both examples would produce usable prompts
|
|
94
|
+
|
|
95
|
+
**Hints:**
|
|
96
|
+
1. Start with: "Generate [FRAMEWORK] unit tests for [FUNCTION]..."
|
|
97
|
+
2. Add: "Include [CASES]. Use [STYLE]."
|
|
98
|
+
3. Example: [FUNCTION]=parsePrice, [CASES]=happy, null, invalid
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
slug: ai-test-generation
|
|
2
|
+
title: "AI-Assisted Test Generation — Using Claude for Coverage"
|
|
3
|
+
version: 1.0.0
|
|
4
|
+
description: "Use AI to generate tests—prompting strategies, review practices, and combining human judgment with AI speed."
|
|
5
|
+
category: quality-assurance
|
|
6
|
+
tags: [ai, testing, test-generation, claude, automation, coverage]
|
|
7
|
+
difficulty: intermediate
|
|
8
|
+
|
|
9
|
+
xp:
|
|
10
|
+
read: 15
|
|
11
|
+
walkthrough: 40
|
|
12
|
+
exercise: 25
|
|
13
|
+
quiz: 20
|
|
14
|
+
quiz-perfect-bonus: 10
|
|
15
|
+
|
|
16
|
+
time:
|
|
17
|
+
quick: 5
|
|
18
|
+
read: 20
|
|
19
|
+
guided: 50
|
|
20
|
+
|
|
21
|
+
prerequisites: [test-strategy]
|
|
22
|
+
related: [ai-pair-programming, prompt-engineering]
|
|
23
|
+
|
|
24
|
+
triggers:
|
|
25
|
+
- "How can AI help me write tests?"
|
|
26
|
+
- "Can Claude generate unit tests?"
|
|
27
|
+
- "How do I use AI for test coverage?"
|
|
28
|
+
- "What's the best way to prompt AI for tests?"
|
|
29
|
+
|
|
30
|
+
visuals:
|
|
31
|
+
diagrams: [diagram-mermaid, diagram-flow]
|
|
32
|
+
quiz-types: [quiz-timed-choice, quiz-matching]
|
|
33
|
+
playground: javascript
|
|
34
|
+
slides: true
|
|
35
|
+
|
|
36
|
+
sources:
|
|
37
|
+
- url: "https://docs.anthropic.com"
|
|
38
|
+
label: "Anthropic Claude Documentation"
|
|
39
|
+
type: docs
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# AI-Assisted Test Generation Quick Reference
|
|
2
|
+
|
|
3
|
+
## Prompt Checklist
|
|
4
|
+
|
|
5
|
+
- [ ] Function/code under test
|
|
6
|
+
- [ ] Framework (Jest, Vitest, Playwright)
|
|
7
|
+
- [ ] Case types (happy, edge, error)
|
|
8
|
+
- [ ] One example test for style
|
|
9
|
+
- [ ] Constraints (no mocks for X, use RTL)
|
|
10
|
+
|
|
11
|
+
## AI Strengths
|
|
12
|
+
|
|
13
|
+
| Strength | Use For |
|
|
14
|
+
|----------|---------|
|
|
15
|
+
| Boilerplate | describe, it, expect structure |
|
|
16
|
+
| Edge cases | Empty, null, boundary suggestions |
|
|
17
|
+
| Test data | Fixtures, mocks, invalid inputs |
|
|
18
|
+
| Test doubles | Stub/mock generation |
|
|
19
|
+
|
|
20
|
+
## AI Weaknesses
|
|
21
|
+
|
|
22
|
+
| Weakness | Human Must |
|
|
23
|
+
|----------|------------|
|
|
24
|
+
| Intent | Provide context and priorities |
|
|
25
|
+
| What matters | Choose what to test |
|
|
26
|
+
| Assertion quality | Review and strengthen |
|
|
27
|
+
| Framework quirks | Specify and verify |
|
|
28
|
+
|
|
29
|
+
## Review Checklist for Generated Tests
|
|
30
|
+
|
|
31
|
+
- [ ] Assertions verify behavior, not just "defined"
|
|
32
|
+
- [ ] Edge cases and errors covered
|
|
33
|
+
- [ ] Mocks justified (not over-used)
|
|
34
|
+
- [ ] Test names are descriptive
|
|
35
|
+
- [ ] Tests are independent
|
|
36
|
+
|
|
37
|
+
## Common Pitfalls
|
|
38
|
+
|
|
39
|
+
| Pitfall | Fix |
|
|
40
|
+
|---------|-----|
|
|
41
|
+
| expect(x).toBeDefined() | Assert expected value (toBe, toEqual) |
|
|
42
|
+
| Over-mocking | Use real deps for integration |
|
|
43
|
+
| Wrong framework | Specify in prompt; refine and regenerate |
|
|
44
|
+
| Missing edge cases | Ask for "boundary and invalid inputs" |
|
|
45
|
+
|
|
46
|
+
## Iteration Loop
|
|
47
|
+
|
|
48
|
+
```
|
|
49
|
+
Prompt → Generate → Run → Review → Refine prompt → (repeat)
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## By Layer
|
|
53
|
+
|
|
54
|
+
| Layer | AI Does | You Do |
|
|
55
|
+
|-------|---------|--------|
|
|
56
|
+
| Unit | Draft + edge cases | Verify assertions, add critical cases |
|
|
57
|
+
| Integration | Setup, fixtures | Verify real flows, DB state |
|
|
58
|
+
| E2E | Steps, selectors | Choose scenarios, reduce flakiness |
|
|
59
|
+
|
|
60
|
+
## One-Liners
|
|
61
|
+
|
|
62
|
+
- **Context wins**: Function + framework + examples = better tests.
|
|
63
|
+
- **Review always**: AI drafts; you verify.
|
|
64
|
+
- **Iterate prompts**: Save what works for your stack.
|
|
65
|
+
- **Human + AI**: You direct; AI speeds you up.
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# AI-Assisted Test Generation Quiz
|
|
2
|
+
|
|
3
|
+
## Question 1
|
|
4
|
+
|
|
5
|
+
What is AI typically good at when generating tests?
|
|
6
|
+
|
|
7
|
+
A) Deciding which tests matter most for your business
|
|
8
|
+
B) Generating boilerplate, edge cases, and test data
|
|
9
|
+
C) Knowing your team's testing conventions without being told
|
|
10
|
+
D) Writing perfect tests that never need review
|
|
11
|
+
|
|
12
|
+
<!-- ANSWER: B -->
|
|
13
|
+
<!-- EXPLANATION: AI excels at generating structure (describe, it, expect), suggesting edge cases, and creating fixtures. It does not know your business priorities or conventions without explicit context. -->
|
|
14
|
+
|
|
15
|
+
## Question 2
|
|
16
|
+
|
|
17
|
+
Why should you review AI-generated tests critically?
|
|
18
|
+
|
|
19
|
+
A) AI always produces bugs
|
|
20
|
+
B) AI often produces shallow assertions and over-mocking that need strengthening
|
|
21
|
+
C) Review is only for style
|
|
22
|
+
D) AI-generated tests don't need review
|
|
23
|
+
|
|
24
|
+
<!-- ANSWER: B -->
|
|
25
|
+
<!-- EXPLANATION: AI commonly produces tests with weak assertions (e.g., toBeDefined), excessive mocking, or missing edge cases. Human review ensures tests actually verify behavior. -->
|
|
26
|
+
|
|
27
|
+
## Question 3
|
|
28
|
+
|
|
29
|
+
What improves AI test generation prompts?
|
|
30
|
+
|
|
31
|
+
A) Longer prompts are always better
|
|
32
|
+
B) Providing the function, framework, example tests, and desired cases
|
|
33
|
+
C) Asking for "comprehensive" tests without specifics
|
|
34
|
+
D) Avoiding any examples to keep output original
|
|
35
|
+
|
|
36
|
+
<!-- ANSWER: B -->
|
|
37
|
+
<!-- EXPLANATION: Context matters: the function under test, the framework (Jest, Vitest), one example test for style, and specific case types (happy, edge, error) all improve output quality. -->
|
|
38
|
+
|
|
39
|
+
## Question 4
|
|
40
|
+
|
|
41
|
+
When is AI most useful for test generation?
|
|
42
|
+
|
|
43
|
+
A) Only for e2e tests
|
|
44
|
+
B) For unit test boilerplate and edge case suggestions; human decides strategy
|
|
45
|
+
C) To replace all manual test writing
|
|
46
|
+
D) Only when you have no tests yet
|
|
47
|
+
|
|
48
|
+
<!-- ANSWER: B -->
|
|
49
|
+
<!-- EXPLANATION: AI is strongest for unit-level drafts and suggestions. Human judgment is essential for prioritization, integration/e2e strategy, and verifying assertions are meaningful. -->
|
|
50
|
+
|
|
51
|
+
## Question 5
|
|
52
|
+
|
|
53
|
+
What should you do when AI generates tests with the wrong framework (e.g., Jest instead of Vitest)?
|
|
54
|
+
|
|
55
|
+
A) Manually rewrite every test
|
|
56
|
+
B) Refine the prompt to specify the framework and regenerate
|
|
57
|
+
C) Switch your project to match the AI output
|
|
58
|
+
D) Use the tests as-is since APIs are similar
|
|
59
|
+
|
|
60
|
+
<!-- ANSWER: B -->
|
|
61
|
+
<!-- EXPLANATION: Refining the prompt to explicitly specify Vitest (vi.fn(), vi.mock()) and regenerating is efficient. Building a prompt library for your stack avoids repeats. -->
|
|
62
|
+
|
|
63
|
+
## Question 6
|
|
64
|
+
|
|
65
|
+
Match the AI capability to the test layer:
|
|
66
|
+
|
|
67
|
+
<!-- VISUAL: quiz-matching -->
|
|
68
|
+
|
|
69
|
+
- Unit tests :: Boilerplate, edge cases, mocks — human verifies assertions
|
|
70
|
+
- Integration tests :: Setup, fixtures, contracts — human verifies real flows
|
|
71
|
+
- E2E tests :: Selectors, steps — human chooses scenarios
|
|
72
|
+
|
|
73
|
+
<!-- ANSWER: (implicit from matching) -->
|
|
74
|
+
<!-- EXPLANATION: AI can draft at all layers, but human responsibility differs. Unit: verify assertions. Integration: verify real system behavior. E2E: choose what matters, avoid flakiness. -->
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# AI-Assisted Test Generation — Resources
|
|
2
|
+
|
|
3
|
+
## AI & Prompting
|
|
4
|
+
|
|
5
|
+
- [Anthropic Claude Documentation](https://docs.anthropic.com/) — Claude API, prompting, best practices.
|
|
6
|
+
- [Claude Prompt Engineering](https://docs.anthropic.com/claude/docs/prompt-engineering) — Context, examples, and structure.
|
|
7
|
+
- [OpenAI Prompt Engineering](https://platform.openai.com/docs/guides/prompt-engineering) — General prompting patterns (apply to Claude).
|
|
8
|
+
- [Prompt Engineering Guide](https://www.promptingguide.ai/) — Techniques for better prompts across models.
|
|
9
|
+
|
|
10
|
+
## Testing Frameworks
|
|
11
|
+
|
|
12
|
+
- [Vitest](https://vitest.dev/) — Fast, ESM-native test runner. Great for JS/TS.
|
|
13
|
+
- [Jest](https://jestjs.io/) — Popular unit testing framework. Large ecosystem.
|
|
14
|
+
- [Playwright](https://playwright.dev/) — E2E testing. AI can help with selectors and flows.
|
|
15
|
+
- [Testing Library](https://testing-library.com/) — User-centric component tests. Specify in prompts.
|
|
16
|
+
|
|
17
|
+
## Articles
|
|
18
|
+
|
|
19
|
+
- [AI-Generated Tests: What to Watch For](https://martinfowler.com/articles/ai-testing.html) — Martin Fowler (if available) or similar. Pitfalls of AI tests.
|
|
20
|
+
- [Using AI for Test Automation](https://www.ministryoftesting.com/articles) — Ministry of Testing. Practical tips.
|
|
21
|
+
- [Test Doubles and Mocks](https://martinfowler.com/bliki/TestDouble.html) — So AI generates the right kind.
|
|
22
|
+
- [Meaningful Assertions](https://kentcdodds.com/blog/what-to-test) — Kent C. Dodds. What to verify.
|
|
23
|
+
|
|
24
|
+
## Tools
|
|
25
|
+
|
|
26
|
+
- [Cursor](https://cursor.com/) — AI-assisted IDE. Inline test generation.
|
|
27
|
+
- [GitHub Copilot](https://github.com/features/copilot) — Test generation in the editor.
|
|
28
|
+
- [Claude Code / Claude Codex](https://www.anthropic.com/product) — Coding-focused Claude.
|
|
29
|
+
- [Mocha / Chai](https://mochajs.org/) — Alternative test framework. Specify in prompts if used.
|
|
30
|
+
|
|
31
|
+
## Best Practices
|
|
32
|
+
|
|
33
|
+
- [Test Strategy — Martin Fowler](https://martinfowler.com/articles/practical-test-pyramid.html) — Foundation for what to test.
|
|
34
|
+
- [Test-Driven Development](https://martinfowler.com/bliki/TestDrivenDevelopment.html) — TDD and AI: who drives?
|
|
35
|
+
- [Refactoring with Tests](https://refactoring.com/) — Safe refactoring; AI-generated tests support this.
|
|
36
|
+
|
|
37
|
+
## Community
|
|
38
|
+
|
|
39
|
+
- [Ministry of Testing](https://www.ministryoftesting.com/) — Testing community, AI in testing discussions.
|
|
40
|
+
- [r/QualityAssurance](https://www.reddit.com/r/QualityAssurance/) — QA discussions, tool experiences.
|
|
41
|
+
- [Claude Community](https://www.anthropic.com/community) — Claude usage and prompting tips.
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
# AI-Assisted Test Generation Walkthrough — Learn by Doing
|
|
2
|
+
|
|
3
|
+
## Before We Begin
|
|
4
|
+
|
|
5
|
+
**Diagnostic Question:** When AI generates tests, what could go wrong? What would you still need to verify or add yourself?
|
|
6
|
+
|
|
7
|
+
**Checkpoint:** You recognize that AI can draft tests but may miss edge cases, use the wrong assertions, or assume a different framework. Human review is essential.
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Step 1: Provide Context for a Test Prompt
|
|
12
|
+
|
|
13
|
+
You want AI to generate tests for this function:
|
|
14
|
+
|
|
15
|
+
<!-- hint:code language="javascript" highlight="1,5" -->
|
|
16
|
+
|
|
17
|
+
```javascript
|
|
18
|
+
function parsePrice(input) {
|
|
19
|
+
if (input == null || input === '') return null;
|
|
20
|
+
const num = parseFloat(String(input).replace(/[^0-9.-]/g, ''));
|
|
21
|
+
return isNaN(num) ? null : Math.round(num * 100) / 100;
|
|
22
|
+
}
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
**Task:** Write a prompt you'd send to Claude (or another AI) to generate unit tests. Include: the function, the framework (e.g., Vitest), what cases you want, and one example of a test style you prefer.
|
|
26
|
+
|
|
27
|
+
**Question:** What would happen if you only said "Generate tests for this function" without context?
|
|
28
|
+
|
|
29
|
+
**Checkpoint:** User includes: function code, Vitest, requested cases (happy, empty, null, invalid string, decimals), and maybe one example test. They understand minimal prompts produce generic output; context yields better tests.
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## Step 2: Review AI-Generated Tests
|
|
34
|
+
|
|
35
|
+
<!-- hint:card type="warning" title="AI test pitfalls" -->
|
|
36
|
+
|
|
37
|
+
Suppose AI produced:
|
|
38
|
+
|
|
39
|
+
```javascript
|
|
40
|
+
test('parses price', () => {
|
|
41
|
+
const result = parsePrice('$19.99');
|
|
42
|
+
expect(result).toBeDefined();
|
|
43
|
+
});
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
**Task:** Why is this test weak? Rewrite it (or describe what to change) so it actually verifies behavior.
|
|
47
|
+
|
|
48
|
+
**Question:** What's the difference between "the code ran" and "the code did the right thing"?
|
|
49
|
+
|
|
50
|
+
**Checkpoint:** User identifies: toBeDefined() only checks non-null. Should assert expect(result).toBe(19.99) or similar. They understand assertions must verify expected output, not just "it didn't crash."
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## Step 3: Generate Tests with Claude
|
|
55
|
+
|
|
56
|
+
**Task:** Pick a small function from your codebase (or use `parsePrice` above). Use Claude to generate unit tests. Provide: the function, framework, and at least 3 case types you want. Run the tests. What passed? What did you have to fix or improve?
|
|
57
|
+
|
|
58
|
+
**Question:** What did you learn about prompting from the first attempt? What would you add to the prompt next time?
|
|
59
|
+
|
|
60
|
+
**Checkpoint:** User completes the task, runs tests, and reflects. They note: maybe add "use toBe for numbers, toBeNull for null", or "include $ and , in input" to improve next output.
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
## Step 4: Use AI for Edge Cases
|
|
65
|
+
|
|
66
|
+
<!-- hint:buttons type="single" prompt="Which edge case would you add first?" options="17 and 121,18.5,eighteen" -->
|
|
67
|
+
|
|
68
|
+
You have a function that validates a user age (must be 18–120). You've written happy path tests.
|
|
69
|
+
|
|
70
|
+
**Task:** Prompt AI: "Suggest 5 edge case inputs for a function that validates age 18–120. Include boundary and invalid cases." List what AI suggests. Then evaluate: which would you actually add to your test suite? Why or why not?
|
|
71
|
+
|
|
72
|
+
**Question:** When would you reject an AI-suggested edge case?
|
|
73
|
+
|
|
74
|
+
**Checkpoint:** User gets suggestions (e.g., 17, 18, 120, 121, -1, "eighteen", 18.5). They evaluate: 18 and 120 are must-haves; 17 and 121 test boundaries; -1 and "eighteen" test invalid; 18.5 might be optional. They reject cases that don't match real usage (e.g., if age is always integer).
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## Step 5: AI for Test Data
|
|
79
|
+
|
|
80
|
+
You need to test an API that accepts `{ name, email, createdAt }`. You want 3 valid and 2 invalid payloads.
|
|
81
|
+
|
|
82
|
+
**Task:** Write a prompt for AI to generate these payloads. What specific requirements would you include? (e.g., email format, date format, invalid examples)
|
|
83
|
+
|
|
84
|
+
**Question:** Why might AI-generated test data still need your review?
|
|
85
|
+
|
|
86
|
+
**Checkpoint:** User writes a clear prompt with constraints (valid email, ISO date, name length). They note: AI might generate data that passes validation but doesn't match real-world edge cases (Unicode, SQL injection attempts); human review catches those.
|
|
87
|
+
|
|
88
|
+
---
|
|
89
|
+
|
|
90
|
+
## Step 6: Iterate on a Failed Prompt
|
|
91
|
+
|
|
92
|
+
<!-- hint:celebrate -->
|
|
93
|
+
|
|
94
|
+
Your first prompt produced tests that used `jest.fn()` but your project uses Vitest (`vi.fn()`). The tests also didn't handle async.
|
|
95
|
+
|
|
96
|
+
**Task:** Write a refined prompt that would fix these issues. What would you add or change?
|
|
97
|
+
|
|
98
|
+
**Question:** How do you build a "prompt library" for test generation over time?
|
|
99
|
+
|
|
100
|
+
**Checkpoint:** User adds: "Use Vitest (vi.fn(), vi.mock())", "This function is async—use async/await in tests". They see value in saving successful prompts for reuse (framework, style, common patterns).
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
# API Design — REST, GraphQL, and Contract-First Thinking
|
|
2
|
+
|
|
3
|
+
<!-- hint:slides topic="API design: REST principles, GraphQL tradeoffs, contract-first design, versioning, pagination, and error handling" slides="6" -->
|
|
4
|
+
|
|
5
|
+
## REST Principles
|
|
6
|
+
|
|
7
|
+
**REST** (Representational State Transfer) models the web as resources identified by URLs, manipulated via HTTP verbs.
|
|
8
|
+
|
|
9
|
+
| Principle | Meaning |
|
|
10
|
+
|-----------|---------|
|
|
11
|
+
| **Resources** | Nouns in URLs: `/users`, `/users/123`, `/users/123/orders` |
|
|
12
|
+
| **HTTP verbs** | GET (read), POST (create), PUT (replace), PATCH (partial update), DELETE (remove) |
|
|
13
|
+
| **Status codes** | 200 OK, 201 Created, 400 Bad Request, 404 Not Found, 429 Too Many Requests |
|
|
14
|
+
| **HATEOAS** | Responses include links to related resources (optional in practice) |
|
|
15
|
+
|
|
16
|
+
## REST Naming Conventions
|
|
17
|
+
|
|
18
|
+
- **Plural nouns:** `/users` not `/user`
|
|
19
|
+
- **Hierarchy:** `/users/123/orders`
|
|
20
|
+
- **No verbs in URL:** Use POST `/users` not `POST /createUser`
|
|
21
|
+
- **Snake_case or camelCase:** Be consistent (JSON often uses camelCase)
|
|
22
|
+
|
|
23
|
+
Example:
|
|
24
|
+
|
|
25
|
+
```http
|
|
26
|
+
GET /users/42/orders?status=active&limit=10
|
|
27
|
+
POST /users
|
|
28
|
+
{
|
|
29
|
+
"email": "alice@example.com",
|
|
30
|
+
"name": "Alice"
|
|
31
|
+
}
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
```mermaid
|
|
35
|
+
sequenceDiagram
|
|
36
|
+
participant Client
|
|
37
|
+
participant Gateway as API Gateway
|
|
38
|
+
participant Server
|
|
39
|
+
participant DB as Database
|
|
40
|
+
Client->>Gateway: HTTP Request
|
|
41
|
+
Gateway->>Server: Forward Request
|
|
42
|
+
Server->>DB: Query
|
|
43
|
+
DB-->>Server: Result
|
|
44
|
+
Server-->>Gateway: Response
|
|
45
|
+
Gateway-->>Client: HTTP Response
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## GraphQL Basics
|
|
49
|
+
|
|
50
|
+
**GraphQL** lets clients request exactly the fields they need with a single endpoint.
|
|
51
|
+
|
|
52
|
+
```graphql
|
|
53
|
+
query {
|
|
54
|
+
user(id: "42") {
|
|
55
|
+
name
|
|
56
|
+
email
|
|
57
|
+
orders(limit: 5) {
|
|
58
|
+
id
|
|
59
|
+
total
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
- **Queries** — Read data
|
|
66
|
+
- **Mutations** — Create, update, delete
|
|
67
|
+
- **Schemas** — Strong typing; tools generate clients
|
|
68
|
+
- **Resolvers** — Server-side functions that fetch each field
|
|
69
|
+
|
|
70
|
+
## REST vs GraphQL
|
|
71
|
+
|
|
72
|
+
```mermaid
|
|
73
|
+
sequenceDiagram
|
|
74
|
+
participant C as Client
|
|
75
|
+
participant R as REST API
|
|
76
|
+
participant G as GraphQL API
|
|
77
|
+
C->>R: GET /users/1
|
|
78
|
+
R-->>C: Full user object
|
|
79
|
+
C->>R: GET /users/1/orders
|
|
80
|
+
R-->>C: Orders
|
|
81
|
+
Note over C,G: vs GraphQL
|
|
82
|
+
C->>G: POST /graphql { user { name orders { total } } }
|
|
83
|
+
G-->>C: Only requested fields, one round-trip
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
| Criterion | REST | GraphQL |
|
|
87
|
+
|-----------|------|--------|
|
|
88
|
+
| **Over-fetching** | Common (full objects) | Client specifies fields |
|
|
89
|
+
| **Under-fetching** | Multiple requests (N+1) | Single request, nested |
|
|
90
|
+
| **Caching** | HTTP cache, CDN | Custom (normalized cache) |
|
|
91
|
+
| **Discoverability** | URLs, OpenAPI | Schema, introspection |
|
|
92
|
+
| **Complexity** | Simpler | Schema, resolvers, tooling |
|
|
93
|
+
|
|
94
|
+
**Use REST** when: CRUD-heavy, HTTP caching matters, clients are simple. **Use GraphQL** when: flexible queries, mobile (bandwidth), many clients with different needs.
|
|
95
|
+
|
|
96
|
+
## Contract-First Design
|
|
97
|
+
|
|
98
|
+
Define the API before coding: **OpenAPI** (Swagger) for REST, **GraphQL schema** for GraphQL.
|
|
99
|
+
|
|
100
|
+
```yaml
|
|
101
|
+
# OpenAPI snippet
|
|
102
|
+
paths:
|
|
103
|
+
/users/{id}:
|
|
104
|
+
get:
|
|
105
|
+
summary: Get user by ID
|
|
106
|
+
parameters:
|
|
107
|
+
- name: id
|
|
108
|
+
in: path
|
|
109
|
+
required: true
|
|
110
|
+
schema:
|
|
111
|
+
type: string
|
|
112
|
+
responses:
|
|
113
|
+
'200':
|
|
114
|
+
description: User object
|
|
115
|
+
'404':
|
|
116
|
+
description: Not found
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
Benefits: generate clients, mock servers, documentation, validation.
|
|
120
|
+
|
|
121
|
+
## API Versioning
|
|
122
|
+
|
|
123
|
+
| Strategy | Example | Pros / Cons |
|
|
124
|
+
|----------|---------|-------------|
|
|
125
|
+
| **URL** | `/v1/users`, `/v2/users` | Clear, cacheable; more URLs |
|
|
126
|
+
| **Header** | `Accept: application/vnd.api+json;version=2` | Clean URLs; less visible |
|
|
127
|
+
| **Query param** | `?version=2` | Simple; can be forgotten |
|
|
128
|
+
| **Media type** | `application/vnd.myapi.v2+json` | RESTful; verbose |
|
|
129
|
+
|
|
130
|
+
Common: **URL versioning** (`/v1/`, `/v2/`) — predictable, easy to route.
|
|
131
|
+
|
|
132
|
+
## Pagination
|
|
133
|
+
|
|
134
|
+
| Strategy | Use Case |
|
|
135
|
+
|----------|----------|
|
|
136
|
+
| **Offset** | `?offset=20&limit=10` — Simple, can skip; inconsistent if data changes |
|
|
137
|
+
| **Cursor** | `?cursor=abc123&limit=10` — Stable for feeds; no random access |
|
|
138
|
+
| **Page** | `?page=3&per_page=10` — Human-friendly; same issues as offset |
|
|
139
|
+
|
|
140
|
+
**Cursor-based** is preferred for feeds and infinite scroll.
|
|
141
|
+
|
|
142
|
+
## Error Handling
|
|
143
|
+
|
|
144
|
+
Return structured errors:
|
|
145
|
+
|
|
146
|
+
```json
|
|
147
|
+
{
|
|
148
|
+
"error": {
|
|
149
|
+
"code": "VALIDATION_ERROR",
|
|
150
|
+
"message": "Invalid email format",
|
|
151
|
+
"details": [
|
|
152
|
+
{ "field": "email", "reason": "Must be a valid email" }
|
|
153
|
+
]
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
Use appropriate status codes: `400` (client error), `401` (unauthorized), `403` (forbidden), `404` (not found), `429` (rate limited), `500` (server error).
|
|
159
|
+
|
|
160
|
+
## Rate Limiting
|
|
161
|
+
|
|
162
|
+
Protect the API: return `429 Too Many Requests` and include headers:
|
|
163
|
+
|
|
164
|
+
```http
|
|
165
|
+
X-RateLimit-Limit: 1000
|
|
166
|
+
X-RateLimit-Remaining: 42
|
|
167
|
+
X-RateLimit-Reset: 1640995200
|
|
168
|
+
Retry-After: 60
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
## Authentication
|
|
172
|
+
|
|
173
|
+
| Method | Use Case |
|
|
174
|
+
|--------|----------|
|
|
175
|
+
| **API Key** | Simple, server-to-server |
|
|
176
|
+
| **OAuth 2.0** | Delegated access, user consent |
|
|
177
|
+
| **JWT** | Stateless, signed tokens; include in `Authorization: Bearer <token>` |
|
|
178
|
+
|
|
179
|
+
Always use HTTPS for credentials.
|
|
180
|
+
|
|
181
|
+
## Key Takeaways
|
|
182
|
+
|
|
183
|
+
- **REST:** Resources, verbs, status codes; good for CRUD
|
|
184
|
+
- **GraphQL:** Flexible queries, one endpoint; good for varied clients
|
|
185
|
+
- **Contract-first:** Define schema/OpenAPI before implementation
|
|
186
|
+
- **Version** explicitly (URL or header)
|
|
187
|
+
- **Pagination:** Prefer cursor for feeds
|
|
188
|
+
- **Errors:** Structured body, correct status codes
|
|
189
|
+
- **Rate limit** and **authenticate** securely
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# API Design Exercises
|
|
2
|
+
|
|
3
|
+
## Exercise 1: REST Resource Design
|
|
4
|
+
|
|
5
|
+
**Task:** Design REST endpoints for a "books" API: list books, get one book, create a book, update a book, delete a book. Include: URL, method, request body (where applicable), and key response codes.
|
|
6
|
+
|
|
7
|
+
**Validation:**
|
|
8
|
+
- [ ] Plural resource name (`/books`)
|
|
9
|
+
- [ ] Correct HTTP verbs for each action
|
|
10
|
+
- [ ] 201 for create, 200 for get/update, 204 for delete
|
|
11
|
+
- [ ] Request body for create and update
|
|
12
|
+
|
|
13
|
+
**Hints:**
|
|
14
|
+
1. GET /books — list, GET /books/:id — get one
|
|
15
|
+
2. POST /books — create (body: title, author, isbn)
|
|
16
|
+
3. PUT or PATCH /books/:id — update
|
|
17
|
+
4. DELETE /books/:id — delete (204 No Content)
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## Exercise 2: GraphQL Query and Mutation
|
|
22
|
+
|
|
23
|
+
**Task:** Design a GraphQL schema and one query + one mutation for a "tasks" API. Query: get task by id with title, status, assignee name. Mutation: create task with title and assigneeId. Write the schema types and the query/mutation.
|
|
24
|
+
|
|
25
|
+
**Validation:**
|
|
26
|
+
- [ ] Task type with id, title, status, assignee
|
|
27
|
+
- [ ] Query: task(id: ID!): Task
|
|
28
|
+
- [ ] Mutation: createTask(title: String!, assigneeId: ID!): Task
|
|
29
|
+
- [ ] Assignee can be embedded or referenced
|
|
30
|
+
|
|
31
|
+
**Hints:**
|
|
32
|
+
1. type Task { id: ID! title: String! status: String assignee: User }
|
|
33
|
+
2. type User { id: ID! name: String }
|
|
34
|
+
3. createTask returns Task (with id from server)
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## Exercise 3: OpenAPI Snippet
|
|
39
|
+
|
|
40
|
+
**Task:** Write OpenAPI 3.0 for `GET /books` and `POST /books`. Include: parameters (optional: author, limit), request/response schemas, status codes 200, 201, 400.
|
|
41
|
+
|
|
42
|
+
**Validation:**
|
|
43
|
+
- [ ] paths./books with get and post
|
|
44
|
+
- [ ] GET has parameters; POST has requestBody
|
|
45
|
+
- [ ] Schemas for Book (id, title, author)
|
|
46
|
+
- [ ] Correct status codes
|
|
47
|
+
|
|
48
|
+
**Hints:**
|
|
49
|
+
1. openapi: 3.0.0, paths, components.schemas
|
|
50
|
+
2. parameters: author (query), limit (query, default 20)
|
|
51
|
+
3. requestBody for POST: application/json, required: title, author
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## Exercise 4: Pagination Comparison
|
|
56
|
+
|
|
57
|
+
**Task:** Compare offset and cursor pagination for a feed of 10,000 items. Scenario: user requests page 5 (offset 40). Between requests, 3 items are inserted at the start. What does the user see with offset vs cursor? Which is better for a social feed?
|
|
58
|
+
|
|
59
|
+
**Validation:**
|
|
60
|
+
- [ ] Offset: might see duplicates or miss items when data shifts
|
|
61
|
+
- [ ] Cursor: stable, no duplicates; better for feeds
|
|
62
|
+
- [ ] Recommendation: cursor for feeds, offset for admin UIs
|
|
63
|
+
|
|
64
|
+
**Hints:**
|
|
65
|
+
1. Offset 40 = items 41–50. After insert, "page 5" might return different items
|
|
66
|
+
2. Cursor points to last seen item; next page is "after cursor"
|
|
67
|
+
3. Social feeds: cursor preferred (consistent infinite scroll)
|
|
68
|
+
|
|
69
|
+
---
|
|
70
|
+
|
|
71
|
+
## Exercise 5: Error and Rate Limit Response
|
|
72
|
+
|
|
73
|
+
**Task:** Design the full HTTP response for: (1) 400 Bad Request — invalid JSON body, (2) 429 Too Many Requests — client exceeded 100 req/min. Include status, headers, and body format.
|
|
74
|
+
|
|
75
|
+
**Validation:**
|
|
76
|
+
- [ ] 400: body has error code, message, optionally details
|
|
77
|
+
- [ ] 429: Retry-After header, optionally X-RateLimit-* headers
|
|
78
|
+
- [ ] Content-Type: application/json
|
|
79
|
+
- [ ] Body is parseable and actionable for clients
|
|
80
|
+
|
|
81
|
+
**Hints:**
|
|
82
|
+
1. 400: { "error": { "code": "INVALID_JSON", "message": "..." } }
|
|
83
|
+
2. 429: Retry-After: 60 (seconds)
|
|
84
|
+
3. X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset
|