From 7a3ecffebb48667dbbbf7d34ba218ddff5b5c64e Mon Sep 17 00:00:00 2001 From: "Patrick Seidler (via Claude Code)" Date: Wed, 5 Aug 2026 21:32:00 +0000 Subject: [PATCH] test: zwei bekannte Flakes entschaerfen MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1) Kollisionstests (booking/beleg): toBe(5000) prueft die falsche Zusage. Die Eindeutigkeit garantiert nicht der Generator, sondern UNIQUE + Retry in booking-core.ts. Bei 40 Bit Entropie liegt die Kollisionswahrscheinlichkeit ueber 5000 Ziehungen bei rund 1:88.000 pro Lauf — der Test waere im Schnitt alle 88.000 Laeufe grundlos rot geworden. Jetzt >= 4995: laesst einzelne Kollisionen zu, schlaegt aber an, wenn die Streuung zusammenbricht. 2) hookTimeout global auf 60 s. Die beforeAll-Hooks der Integrationstests werfen das Schema weg und fahren die ganze Migrationskette hoch; deren Dauer waechst mit jeder Migration, der Standard-Timeout nicht. email-change.test.ts lief deshalb sporadisch in einen Timeout, einzeln aber gruen. Beides ist dieselbe Sorge: Ein roter Lauf ohne echten Fehler wird beim naechsten Mal weggeklickt — und dann faellt ein echter Fehler auch nicht mehr auf. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_018YNj1kkesDywuEGvNweBHM --- app/src/lib/polls/__tests__/beleg.test.ts | 8 ++++++-- app/src/lib/verification/__tests__/booking.test.ts | 13 +++++++++++-- app/vitest.config.ts | 8 ++++++++ 3 files changed, 25 insertions(+), 4 deletions(-) diff --git a/app/src/lib/polls/__tests__/beleg.test.ts b/app/src/lib/polls/__tests__/beleg.test.ts index 4439891..70e3bcc 100644 --- a/app/src/lib/polls/__tests__/beleg.test.ts +++ b/app/src/lib/polls/__tests__/beleg.test.ts @@ -59,10 +59,14 @@ describe("Beleg-Code Format (Unit)", () => { } }); - it("streut breit (CSPRNG) — keine Kollisionen über 5000 Codes", () => { + // Siehe verification/__tests__/booking.test.ts: geprüft wird die Streuung des + // CSPRNG, nicht die Eindeutigkeit — für die sorgt der UNIQUE-Constraint mit + // Retry. toBe(5000) wäre bei 40 Bit Entropie im Schnitt alle 88.000 Läufe + // grundlos rot geworden (Geburtstagsproblem). + it("streut breit (CSPRNG) — praktisch kollisionsfrei über 5000 Codes", () => { const set = new Set(); for (let i = 0; i < 5000; i++) set.add(generateBelegCode()); - expect(set.size).toBe(5000); + expect(set.size).toBeGreaterThanOrEqual(4995); }); }); diff --git a/app/src/lib/verification/__tests__/booking.test.ts b/app/src/lib/verification/__tests__/booking.test.ts index aa83e60..62d45d2 100644 --- a/app/src/lib/verification/__tests__/booking.test.ts +++ b/app/src/lib/verification/__tests__/booking.test.ts @@ -60,10 +60,19 @@ describe("Termin-Code Format (Unit)", () => { expect(c.replace(/^TERMIN-/, "")).not.toMatch(/[ILOU]/); } }); - it("streut breit (keine Kollision über 5000)", () => { + // Prüft die STREUUNG des Generators, nicht die Eindeutigkeit der Codes — die + // garantiert nicht er, sondern UNIQUE + Retry in booking-core.ts (fünf + // Versuche mit onConflictDoNothing auf den Code-Constraint). + // + // toBe(5000) war deshalb die falsche Erwartung und dazu flaky: Bei 40 Bit + // Entropie liegt die Kollisionswahrscheinlichkeit über 5000 Ziehungen bei + // rund 1:88.000 pro Lauf (Geburtstagsproblem) — der Test wäre im Schnitt alle + // 88.000 Läufe grundlos rot geworden. Die Schranke lässt einzelne Kollisionen + // zu und schlägt trotzdem an, wenn die Streuung wirklich zusammenbricht. + it("streut breit (praktisch kollisionsfrei über 5000 Codes)", () => { const set = new Set(); for (let i = 0; i < 5000; i++) set.add(generateBookingCode()); - expect(set.size).toBe(5000); + expect(set.size).toBeGreaterThanOrEqual(4995); }); }); diff --git a/app/vitest.config.ts b/app/vitest.config.ts index 837127d..a044606 100644 --- a/app/vitest.config.ts +++ b/app/vitest.config.ts @@ -12,6 +12,14 @@ export default defineConfig({ alias: { "@": path.resolve(__dirname, "./src"), }, + // Setup-Hooks der Integrationstests werfen das Schema weg und fahren die + // gesamte Migrationskette neu hoch. Deren Dauer wächst mit jeder Migration, + // der Standard-Timeout von 10 s aber nicht — email-change.test.ts lief + // deshalb sporadisch in einen beforeAll-Timeout, einzeln aber grün. Ein + // roter Lauf ohne echten Fehler ist teurer als eine großzügige Schranke: + // Er wird beim nächsten Mal weggeklickt, und dann fällt ein echter Fehler + // auch nicht mehr auf. + hookTimeout: 60_000, // Sequentielle Ausführung: Integrationstests teilen dieselbe Test-DB // und würden sich bei paralleler Ausführung gegenseitig beim Schema-Reset stören. pool: "forks",