Flaky Tests — Cheat Sheet

Tag: testing, jest, playwright, cypress, ci-cd, automation, debugging

Livello: intermedio

TL;DR: Un flaky test fallisce o passa in modo non deterministico a parità di codice. Si isola trovando race condition, timing o shared state.

Concetti chiave

Un test flaky produce esiti intermittenti senza modifiche al codice sorgente.

Riduce la fiducia nella suite di CI/CD e incentiva a ignorare i fallimenti.

Causa primaria: race condition asincrone tra rendering DOM, chiamate API e asserzioni.

Causa frequente: dipendenza da timing statici o sleep rigidi anziché polling esplicito.

Causa sistemica: shared mutable state tra test eseguiti in parallelo.

Dipendenza da risorse esterne lente, non isolate o instabili via rete.

Date, fusi orari o generatori casuali non mockati creano flakiness temporale.

Ordine di esecuzione dei test non isolato (inquinamento del database o storage).

Strategia di mitigazione: quarantena immediata del test per sbloccare la pipeline.

Soluzione strutturale: auto-retry limitato in CI unito a monitoraggio del tasso di flakiness.

Domande tipiche e risposte pronte

Q: Come affronti un test flaky identificato in pipeline?R: Isolo subito il test mettendolo in quarantena per non bloccare il team, poi riproduco localmente con loop di ripetizione ad alta concorrenza. Analizzo leak di stato, chiamate asincrone senza await e sostituisco eventuali timeout statici con asserzioni a polling.

Q: L'auto-retry in CI è una soluzione valida per i flaky test?R: È un cuscinetto temporaneo per evitare falsi negativi bloccanti, ma non la soluzione. Se non tracciato e corretto alla radice, nasconde bug reali e degrada i tempi di build.

Insidie e errori comuni

Uso di sleep o pause temporali fisse invece di attendere eventi o selettori.

Pulizia incompleta del database, session storage o mock tra un test e l'altro.

Asserzioni su elenchi non ordinati deterministiche solo in locale ma non in CI.

Parallelizzazione della suite con risorse condivise non isolate per worker.

Test che dipendono dall'ordine alfabetico o casuale di esecuzione dei file.

Snippet e comandi

# Eseguire un test ripetutamente fino al primo fallimento (Playwright)
npx playwright test tests/auth.spec.ts --repeat-each=50 --workers=4

TypeScript

// Anti-pattern: attesa fissa incline a flakiness
await page.waitForTimeout(3000);
expect(await page.locator('.badge').innerText()).toBe('Completato');

// Best practice: attesa condizionale su stato del DOM
await expect(page.locator('.badge')).toHaveText('Completato', { timeout: 5000 });

TypeScript

// Isolamento dello stato tra test
beforeEach(async () => {
  await db.clean();
  jest.clearAllMocks();
  localStorage.clear();
});

Da ripassare

[ ] Meccanismi di auto-waiting nativi nei runner E2E (Playwright vs Cypress)

[ ] Strategie di mock deterministico per Date, clock di sistema e Math.random

[ ] Pattern di quarantena e tagging automatico in pipeline CI/CD

[ ] Isolamento dei contesti di storage e database per worker paralleli

Jarvis Interviews
Jarvis