Skip to content

Commit e785245

Browse files
authored
docs: adds supplemental 4 lesson (#825)
Signed-off-by: Anthony D. Mays <[email protected]>
1 parent cf4032e commit e785245

File tree

3 files changed

+202
-1
lines changed

3 files changed

+202
-1
lines changed
Lines changed: 198 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,198 @@
1+
import htm from "htm";
2+
import { createElement } from "react";
3+
import { CodeSlide, DemoSlide, Lesson } from "../Layouts/index.js";
4+
5+
const html = htm.bind(createElement);
6+
7+
function Supplemental4() {
8+
return html`
9+
<${Lesson} title="Integration Testing" lessonId="supplemental_4" subtitle="Supplemental 4">
10+
<section>
11+
<p><em>Unit tests</em> verify individual functions work in isolation.</p>
12+
</section>
13+
<section>
14+
<p><em>Integration tests</em> verify that multiple components work together correctly.</p>
15+
</section>
16+
<section>
17+
<p>Integration tests catch bugs that unit tests miss—like <em>API failures</em>, <em>database issues</em>, and <em>UI interactions</em>.</p>
18+
</section>
19+
<section class="ml-bullet-slide">
20+
<h3>Unit vs Integration Testing</h3>
21+
<ul>
22+
<li class="fragment"><em>Unit</em>: Fast, isolated, mocks dependencies</li>
23+
<li class="fragment"><em>Integration</em>: Slower, uses real services, tests workflows</li>
24+
<li class="fragment">Both are essential for quality software</li>
25+
</ul>
26+
</section>
27+
<section>
28+
<p>Integration tests often require <em>databases</em>, <em>APIs</em>, and <em>browsers</em> to be running.</p>
29+
</section>
30+
<section class="ml-bullet-slide">
31+
<h3>Common Integration Testing Tools</h3>
32+
<ul>
33+
<li class="fragment"><em>Browser automation</em>: Playwright, Selenium, Cypress</li>
34+
<li class="fragment"><em>API testing</em>: Supertest, REST Assured</li>
35+
<li class="fragment"><em>Screenshot/visual testing</em>: Percy, Chromatic</li>
36+
</ul>
37+
</section>
38+
<section>
39+
<p><em>Playwright</em> is a modern browser automation tool that makes integration testing fast and reliable.</p>
40+
</section>
41+
<section class="ml-bullet-slide" fontSize=".42em">
42+
<h3>Why Playwright?</h3>
43+
<ul>
44+
<li class="fragment">Tests Chrome, Firefox, Safari, and mobile browsers</li>
45+
<li class="fragment">Auto-waits for elements (no flaky tests)</li>
46+
<li class="fragment">Built-in screenshot and video recording</li>
47+
</ul>
48+
</section>
49+
<section>
50+
<p>Let's set up Playwright for a web app.</p>
51+
</section>
52+
<${CodeSlide} lang="bash" badge="Terminal" fontSize=".42em" lineNumbers=true>
53+
# Install Playwright
54+
npm init playwright@latest
55+
56+
# Installs test runner, browsers, and example tests
57+
<//>
58+
<${CodeSlide} lang="typescript" badge="tests/example.spec.ts" fontSize=".38em" lineNumbers=true>
59+
import { test, expect } from '@playwright/test';
60+
61+
test('homepage loads correctly', async ({ page }) => {
62+
// Navigate to homepage
63+
await page.goto('http://localhost:3000');
64+
65+
// Check title
66+
await expect(page).toHaveTitle(/My App/);
67+
68+
// Click button and verify result
69+
await page.click('button#submit');
70+
await expect(page.locator('.result')).toHaveText('Success!');
71+
});
72+
<//>
73+
<${CodeSlide} lang="bash" badge="Terminal" fontSize=".42em" lineNumbers=true>
74+
# Run all tests
75+
npx playwright test
76+
77+
# Run tests in headed mode (see browser)
78+
npx playwright test --headed
79+
80+
# Open test report
81+
npx playwright show-report
82+
<//>
83+
<section>
84+
<p>Integration tests need services running—use <em>scripts</em> to automate setup.</p>
85+
</section>
86+
<${CodeSlide} lang="json" badge="package.json" fontSize=".36em" lineNumbers=true>
87+
{
88+
"scripts": {
89+
"start": "node app.js",
90+
"test:unit": "jest",
91+
"test:integration": "playwright test",
92+
"test:integration:headed": "playwright test --headed",
93+
"pretest:integration": "npm run db:setup && npm run start:ci",
94+
"start:ci": "node app.js &",
95+
"db:setup": "node scripts/setup-db.js"
96+
}
97+
}
98+
<//>
99+
<section>
100+
<p>Use <em>wait-on</em> to ensure services are ready before running tests.</p>
101+
</section>
102+
<${CodeSlide} lang="json" badge="package.json" fontSize=".38em" lineNumbers=true>
103+
{
104+
"scripts": {
105+
"pretest:integration": "npm run start:ci",
106+
"start:ci": "node app.js & wait-on http://localhost:3000",
107+
"test:integration": "playwright test"
108+
},
109+
"devDependencies": {
110+
"wait-on": "^7.0.0"
111+
}
112+
}
113+
<//>
114+
<section>
115+
<p><em>Docker</em> enables <em>hermetic testing</em>—fully isolated, reproducible test environments.</p>
116+
</section>
117+
<section>
118+
<p>Hermetic tests run in clean containers with <em>no external dependencies</em> or state.</p>
119+
</section>
120+
<${CodeSlide} lang="yaml" badge="docker-compose.test.yml" fontSize=".32em" lineNumbers=true>
121+
services:
122+
db:
123+
image: postgres:16-alpine
124+
environment:
125+
POSTGRES_DB: testdb
126+
POSTGRES_USER: test
127+
POSTGRES_PASSWORD: test
128+
129+
app:
130+
build: .
131+
environment:
132+
DATABASE_URL: postgres://test:test@db:5432/testdb
133+
depends_on:
134+
- db
135+
ports:
136+
- "3000:3000"
137+
138+
tests:
139+
build:
140+
context: .
141+
dockerfile: Dockerfile.test
142+
depends_on:
143+
- app
144+
command: npx playwright test
145+
<//>
146+
<${CodeSlide} lang="bash" badge="Terminal" fontSize=".42em" lineNumbers=true>
147+
# Run tests in isolated Docker environment
148+
docker compose -f docker-compose.test.yml up --abort-on-container-exit
149+
150+
# Clean up after tests
151+
docker compose -f docker-compose.test.yml down -v
152+
<//>
153+
<section>
154+
<p><em>GitHub Actions</em> can run your Docker-based tests on every push and pull request.</p>
155+
</section>
156+
<${CodeSlide} lang="yaml" badge=".github/workflows/test.yml" fontSize=".30em" lineNumbers=true>
157+
name: Integration Tests
158+
159+
on: [push, pull_request]
160+
161+
jobs:
162+
test:
163+
runs-on: ubuntu-latest
164+
steps:
165+
- uses: actions/checkout@v4
166+
167+
- name: Set up Docker Buildx
168+
uses: docker/setup-buildx-action@v3
169+
170+
- name: Run integration tests
171+
run: |
172+
docker compose -f docker-compose.test.yml up \\
173+
--abort-on-container-exit --exit-code-from tests
174+
175+
- name: Upload test results
176+
if: always()
177+
uses: actions/upload-artifact@v4
178+
with:
179+
name: playwright-report
180+
path: playwright-report/
181+
<//>
182+
<section>
183+
<p>With Docker and CI, every code change is automatically tested in a <em>clean</em>, <em>consistent</em> environment.</p>
184+
</section>
185+
<section class="ml-bullet-slide">
186+
<h3>Integration Testing Best Practices</h3>
187+
<ul>
188+
<li class="fragment">Keep tests fast—use parallelization</li>
189+
<li class="fragment">Test critical user flows, not everything</li>
190+
<li class="fragment">Use Docker for consistency across machines</li>
191+
<li class="fragment">Run tests in CI on every commit</li>
192+
</ul>
193+
</section>
194+
<${DemoSlide} />
195+
<//>`;
196+
}
197+
198+
export default Supplemental4;

slides/src/Slides/Lessons/index.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import Lesson25 from "./Lesson25.js";
2727
import Supplemental1 from "./Supplemental1.js";
2828
import Supplemental2 from "./Supplemental2.js";
2929
import Supplemental3 from "./Supplemental3.js";
30+
import Supplemental4 from "./Supplemental4.js";
3031

3132
export {
3233
Lesson00,
@@ -57,6 +58,7 @@ export {
5758
Lesson25,
5859
Supplemental1,
5960
Supplemental2,
60-
Supplemental3
61+
Supplemental3,
62+
Supplemental4
6163
};
6264

slides/src/Slides/Slides.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ function Slides() {
4242
<${lessons.Supplemental1} />
4343
<${lessons.Supplemental2} />
4444
<${lessons.Supplemental3} />
45+
<${lessons.Supplemental4} />
4546
</div>`;
4647
}
4748

0 commit comments

Comments
 (0)