Files
uni/slides/dhbw/05_testing.md

7.1 KiB
Raw Blame History

marp, theme, paginate, backgroundColor, header, footer, title
marp theme paginate backgroundColor header footer title
true gaia true Web Engineering DHBW Stuttgart Michael Czechowski SoSe 2026 Testing
<style> :root { --color-foreground: #1a1a2e; --color-highlight: #005f8a; --color-dimmed: #4a6a7a; } section.invert { --color-foreground: #fff; } section { font-size: 1.7rem; } h1 { color: #005f8a; } section.invert h1 { color: #fff; } pre { background: #0f1e2e; color: #00b4d8; border-radius: 8px; border-left: 3px solid #005f8a; } pre code { background: transparent; color: inherit; } code { background: #1a3a4a; color: #00b4d8; padding: 0.15em 0.4em; border-radius: 4px; } a { color: var(--color-highlight); } </style>

Testing

Unit · Integration · End-to-End


Inhalt

  1. Test Automation Pyramid
  2. Test Automation Trophy
  3. Static Code Analysis
  4. Unit Tests
  5. Integration Tests
  6. End-to-End Tests (API + Client)
  7. Live Coding

Test Automation Pyramid

            ▲  manual / exploratory
           ▲ ▲   E2E (UI + API)
          ▲▲▲▲   Integration (class + real deps)
         ▲▲▲▲▲▲   Unit (class + mocked deps)
        ▲▲▲▲▲▲▲▲   Static analysis (compiler, linter)
  • Oben: wenige, langsam, teuer, brüchig
  • Unten: viele, schnell, billig, stabil

Test Automation V-Modell

Requirements ────────────► Acceptance Test
   ▼                            ▲
Architecture ────────► Integration Test
   ▼                            ▲
Modular Design ──────► Unit Test
   ▼                            ▲
        Implementation

Jede Design-Phase hat Testpendant. Testfälle früh ableiten.


Test Automation Trophy (Kent C. Dodds)

        🏆
   ┌─────────┐
   │   E2E   │  ← klein
   ├─────────┤
   │ Integr. │  ← GROSS (Hauptfokus)
   ├─────────┤
   │  Unit   │  ← mittel
   ├─────────┤
   │ Static  │  ← Basis (TS, ESLint)
   └─────────┘

Andere Gewichtung: Integration im Zentrum, Static als breite Basis.


Testing Frameworks Übersicht

Static Code Analysis

  • ESLint, Prettier, SonarQube, TypeScript

Unit + Integration

  • jest, mocha, vitest

End-to-End

  • Cypress, Playwright, supertest (API only)

Visual / Interaction

  • Storybook, Chromatic

Static Code Analysis

  • Läuft in Millisekunden
  • Findet Syntaxfehler, ungenutzte Variablen, undefined refs
  • Kein Runtime-Overhead
  • Erste Verteidigungslinie
npm i -D eslint prettier
npx eslint --init
npx prettier --write .

SonarQube: zentraler Server, Code Smells, Security, Coverage.


Unit Tests Eigenschaften

  • Isolation jede Dependency gemockt
  • Deterministisch gleicher Input → gleicher Output
  • Schnell kein I/O, kein Netzwerk, kein FS
  • Fokussiert eine Funktion pro Test

Unit Test Beispiel (vitest)

// cache.unit.test.js
import { describe, it, expect } from "vitest";
import { Cache } from "./cache.js";

describe("Cache", () => {
  it("creates and retrieves data with custom key", () => {
    const cache = new Cache();
    const data = { user: "wolfgang", city: "stuttgart" };

    const key = cache.create(data, "custom-key");

    expect(key).toBe("custom-key");
    expect(cache.get("custom-key")).toEqual(data);
  });
});

Integration Tests Eigenschaften

  • Reale Komponenten echte Cache + Express-Instanzen
  • Supertest-Magie simuliert HTTP ohne Server-Startup
  • In-Process alles im selben Node-Prozess
  • Kein Netzwerk keine TCP-Connections

→ teste Zusammenspiel mehrerer Module ohne Deployment.


Integration Test Beispiel (supertest)

// app.integration.test.js
import request from "supertest";
import { app, cache } from "./app.js";

test("full CRUD lifecycle with real cache", async () => {
  const res = await request(app)
    .post("/api/entries")
    .send({ name: "integration-test", status: "active" });

  expect(res.status).toBe(201);
  const { key } = res.body;

  expect(cache.keys()).toContain(key);
});

End-to-End Tests (API)

  • Echter Server HTTP auf TCP-Port
  • Echtes Netzwerk fetch über localhost
  • Echte Umgebung CORS, Middleware-Stack
  • User-Perspektive exakt was Clients sehen

E2E API Test Beispiel

// index.e2e.test.js
import { createServer } from "node:http";
import { app } from "./app.js";

let server;
const TEST_PORT = 8081;
const baseUrl = `http://localhost:${TEST_PORT}`;

beforeAll(async () => {
  server = createServer(app);
  await new Promise((r) => server.listen(TEST_PORT, r));
});

afterAll(() => server.close());

test("complete user journey", async () => {
  const res = await fetch(`${baseUrl}/api`, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ message: "e2e", timestamp: Date.now() }),
  });
  expect(res.status).toBe(201);
});

End-to-End Tests (Client)

  • Echter Browser Chromium / Firefox / WebKit
  • Echtes DOM Klicks, Tippen, Scrollen
  • Echtes Rendering CSS, async Operationen
  • Cross-Origin Client ↔ Server-Kommunikation

Tools: Cypress, Playwright


Cypress Minimalbeispiel

// cypress/e2e/counter.cy.js
describe("Counter App", () => {
  it("increments on click", () => {
    cy.visit("http://localhost:3000");
    cy.contains("button", "Clicked 0 times").click();
    cy.contains("button", "Clicked 1 times");
  });
});
npx cypress open    # GUI
npx cypress run     # headless / CI

Playwright Minimalbeispiel

// tests/counter.spec.js
import { test, expect } from "@playwright/test";

test("counter increments", async ({ page }) => {
  await page.goto("http://localhost:3000");
  await page.getByRole("button").click();
  await expect(page.getByRole("button")).toContainText("Clicked 1 times");
});
npx playwright test
npx playwright test --ui

Coverage Reports

npx vitest run --coverage
File          | % Stmts | % Branch | % Funcs | % Lines
--------------|---------|----------|---------|--------
cache.js      |   95.2  |   80.0   |  100.0  |  95.2
app.js        |   88.7  |   75.0   |   90.0  |  88.7
  • lcov.info → CI / SonarQube
  • HTML Report → coverage/index.html

Best Practices

  • AAA: Arrange · Act · Assert
  • Tests sind Dokumentation beschreibend benennen
  • Ein Verhalten pro Test
  • Keine Logik im Test (keine if/for)
  • Test Doubles: stub, mock, spy, fake
  • CI: Tests bei jedem Push

Live Coding

Repo: node-cache-api

git clone https://github.com/nextlevelshit/node-cache-api
cd node-cache-api
npm install
npm test          # unit + integration
npm run test:e2e  # e2e

Fragen?

Hausaufgabe: Eigene Projektidee mit mind. 1 Unit + 1 Integration Test starten.