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.
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.
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.
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.
# 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();
});
[ ] 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