Test automatizzati: il fondamento della velocità ingegneristica
I test manuali sono lenti, costosi e inaffidabili. Come costruire una solida strategia di test end-to-end (E2E) utilizzando Playwright e GitHub Actions.
Perché Maison Code ne parla
In Maison Code Paris, agiamo come la coscienza architettonica dei nostri clienti. Spesso ereditiamo stack “moderni” costruiti senza una comprensione fondamentale della scala.
Discutiamo di questo argomento perché rappresenta un punto di svolta critico nella maturità ingegneristica. Implementarlo correttamente differenzia un MVP fragile da una piattaforma resiliente di livello aziendale.
La paura del dispiegamento
Ogni ingegnere del software conosce la sensazione. Sono le 16:00 di venerdì. Hai appena unito una richiesta di pull. La pipeline di distribuzione diventa verde. Dovresti essere felice. Ma stai sudando. “Ho interrotto il flusso di pagamento?” “Ho violato la reimpostazione della password?” “Ho testato il menu mobile su Safari?” Se ti affidi al Test manuale (cliccando tu stesso sul sito web), vivi in un costante stato di paura. Gli esseri umani sono pessimi nei test di regressione. Ci annoiamo. Ci mancano le cose. Testiamo il “Percorso Felice” e dimentichiamo i casi limite. Man mano che la codebase cresce, il tempo necessario per testarla manualmente cresce in modo lineare. Alla fine, smetti di testare. Questo è il momento in cui i bug penetrano nella produzione. E quando i bug trapelano, perdi entrate. Perdi la fiducia. I Test automatizzati sono la cura per questa paura. Trasforma l’implementazione da un “Evento ad alto rischio” in un “Non evento”.
Perché Maison Code parla di test automatizzati
Noi di Maison Code collaboriamo con marchi di lusso di alto livello e piattaforme di e-commerce ad alto traffico. I nostri clienti generano migliaia di euro al minuto durante i picchi di vendita (Black Friday, Natale). Un bug “minore” nel flusso di pagamento non costituisce un inconveniente; è una catastrofe finanziaria. Abbiamo visto brand perdere 50.000 dollari in un’ora perché un pulsante “Aggiungi al carrello” era coperto da un errore Z-Index su iPhone 12. Parliamo di Test Automatizzati perché La stabilità è ricavo. Non vendiamo “codice”. Vendiamo “Affidabilità”. L’implementazione di una solida suite E2E è spesso la prima cosa che facciamo quando controlliamo la codebase legacy di un cliente. Arresta l’emorragia e ci consente di effettuare il refactoring con sicurezza.
1. La piramide dei test: un quadro strategico
Mike Cohn ha reso popolare il concetto di “Test Pyramid”, che rimane lo standard di riferimento per la strategia di test. Definisce la distribuzione ideale dei test nella tua suite.
-
Test unitari (70%):
- Ambito: funzioni o classi individuali.
- Velocità: Millisecondi.
- Costo: Economico.
- Strumento: Jest, Vitest.
- Esempio:
add(2, 2) === 4.
-
Test di integrazione (20%):
- Ambito: Interazioni tra componenti (ad esempio, il genitore che passa oggetti di scena al figlio).
- Velocità: Secondi.
- Costo: Medio.
- Strumento: Libreria di test React.
-
Test end-to-end (E2E) (10%):
- Ambito: flussi utente completi in un browser reale.
- Velocità: Minuti.
- Costo: costoso (calcolo pesante).
- Strumento: Drammaturgo, Cypress.
In questo articolo ci concentreremo sulla cima della piramide: Test E2E.
Perché? Perché fornisce il coefficiente di fiducia più elevato.
Uno unit test può superare anche se il pulsante “Invia” è nascosto da un bug CSS z-index.
Un test E2E fallirà perché tenta di fare clic sul pulsante.
Se un test E2E dice “Articolo acquistato dall’utente”, puoi essere sicuro al 99,9% che gli utenti possano acquistare articoli.
2. Lo strumento di scelta: il drammaturgo
Per un decennio, il Selenio è stato lo standard. Era lento, basato su Java e notoriamente instabile. Poi è arrivato Cipresso. È stato un miglioramento enorme, con un’ottima esperienza per gli sviluppatori, ma presentava limitazioni architettoniche (esecuzione all’interno della sandbox del browser, supporto multi-scheda limitato). Oggi lo standard del settore è Playwright (di Microsoft). Perché drammaturgo?
- Velocità: esegue test in parallelo su più processi di lavoro.
- Affidabilità: dispone di “Attesa automatica”. Attende che gli elementi siano utilizzabili prima di interagire. Niente più “sonno (1000)”.
- Multi-browser: testa in modo nativo su Chromium, Firefox e WebKit (Safari).
- Tracciamento: registra un video completo e una traccia DOM di ogni errore, rendendo banale il debug.
3. Implementazione: testare un flusso di pagamento
Diamo un’occhiata a un esempio del mondo reale. Vogliamo verificare che un utente ospite possa acquistare un prodotto.
“dattiloscritto”. //test/checkout.spec.ts importa { test, aspetta } da ‘@drammaturgo/test’;
test.describe(‘Flusso di pagamento’, () => {
// Isola l’ambiente di test test.beforeEach(asincrono ({ pagina }) => { // Reimposta cookie/archiviazione attendono page.context().clearCookies(); });
test(‘L’utente ospite può acquistare un articolo’, async ({ page }) => { // 1. Navigazione console.log(‘Navigazione alla pagina del prodotto…’); attendono page.goto(‘/products/silk-shirt’); wait wait(page).toHaveTitle(/Silk Shirt/);
// 2. Aggiungi al carrello
// Utilizza localizzatori rivolti all'utente (Ruolo, Etichetta, Testo)
// Evita selettori CSS come '.btn-primary' (fragile)
attendono page.getByRole('button', { name: 'Aggiungi al carrello' }).click();
// 3. Verifica il cassetto del carrello
const cartDrawer = page.getByTestId('carrello-cassetto');
wait wait(cartDrawer).toBeVisible();
wait wait(cartDrawer).toContainText('Camicia di seta');
// 4. Procedi al pagamento
attendono page.getByRole('link', { name: 'Checkout' }).click();
attendono wait(pagina).toHaveURL(/.*\/checkout/);
// 5. Compila il modulo (pagamento parodia)
attendono page.getByLabel('Email').fill('test-bot@maisoncode.paris');
attendono page.getByLabel('Nome').fill('Test');
attendono page.getByLabel('Cognome').fill('Bot');
attendono page.getByLabel('Indirizzo').fill('123 Test St');
// 6. Pagamento (Stripe Mock)
// In rigoroso E2E, potremmo utilizzare una Stripe Test Card.
attendono page.getByLabel('Numero carta').fill('4242 4242 4242 4242');
attendono page.getByLabel('Scadenza').fill('12/30');
attendono page.getByLabel('CVC').fill('123');
// 7. Invia
attendono page.getByRole('button', { name: 'Paga adesso' }).click();
// 8. Affermare il successo
// Aumenta il timeout perché l'elaborazione dei pagamenti richiede tempo
attendono wait(page.getByText('Grazie per il tuo ordine')).toBeVisible({ timeout: 15000 });
});
});
## 4. Gestire la "flakiness" (The Silent Killer)
Un **Flaky Test** è un test che supera il 90% delle volte e fallisce il 10% delle volte, senza alcuna modifica al codice.
La fragilità è il nemico.
Se gli sviluppatori smettono di fidarsi dei test ("Oh, eseguilo nuovamente, è instabile"), la suite di test diventa inutile.
**Cause comuni**:
1. **Latenza di rete**: l'API impiega 5,1 secondi quando il timeout è 5 secondi.
2. **Animazione**: clic su un pulsante mentre sta ancora scorrendo.
3. **Contaminazione dei dati**: il test A elimina un utente necessario al test B.
**Soluzioni**:
1. **Derisione (intercettazione di rete)**:
Invece di chiamare la vera Contentful API (che potrebbe essere lenta), intercetta la richiesta e restituisce un JSON statico.
"dattiloscritto".
attendono page.route('**/api/products', route => {
route.fulfill({ percorso: 'mock-data/products.json' });
});
```
Ciò rende il test 10 volte più veloce e deterministico al 100%.
2. **Nuovi tentativi**:
Configura CI per ritentare automaticamente i test falliti.
"tentativi: 2".
Se passa al nuovo tentativo, è instabile, ma almeno non blocca la distribuzione.
## 5. Test di regressione visiva (Pixel Perfect)
Il drammaturgo verifica la funzionalità ("Il pulsante è selezionabile?").
Non controlla l'estetica ("Il bottone è rosa?").
Se elimini accidentalmente `main.css`, Playwright potrebbe comunque passare (il pulsante è cliccabile, semplicemente invisibile).
**Test di regressione visiva** (istantanee di Percy / Cromatico / Drammaturgo) risolve questo problema.
`await wait(page).toHaveScreenshot();`
1. Fai uno screenshot della pagina.
2. Confrontala con la "Immagine d'Oro" (Baseline).
3. Se i pixel differiscono di > 1%, fallire il test.
Questo rileva "regressioni CSS" che nessun test funzionale potrebbe mai.
## 6. Azioni GitHub: il gatekeeper automatizzato
Non esegui test sul tuo laptop. Li esegui su **CI (Continuous Integration)**.
Ogni volta che esegui il push su GitHub, viene eseguito un flusso di lavoro.
```yaml
# .github/workflows/e2e.yml
nome: drammaturgo E2E
su:
spingere:
rami: [principale]
pull_request:
rami: [principale]
lavori:
prova:
minuti di timeout: 60
funziona su: ubuntu-latest
passaggi:
- utilizza: azioni/checkout@v3
- utilizza: actions/setup-node@v3
con:
versione del nodo: 18
- nome: Installa Deps
corsa: npm ci
- nome: Installa browser
esegui: npx playwright install --with-deps
- nome: Run Playwright
esegui: test del drammaturgo npx
ambiente:
CI: vero
BASE_URL: ${{ github.event.deployment.payload.web_url }} // Prova l'URL di anteprima di Vercel
- nome: Carica rapporto
utilizza: azioni/upload-artifact@v3
se: sempre()
con:
nome: drammaturgo-report
percorso: drammaturgo-report/
7. Il costo della CI (ottimizzazione)
L’esecuzione di 500 test E2E su ogni commit è costosa (minuti di GitHub Actions). Strategie di ottimizzazione:
- Sharding: suddivisione dei test su 10 macchine per un’esecuzione 10 volte più veloce.
npx drammaturgo test --shard=1/10. - Solo progetti interessati: utilizza Nx o Turbo per eseguire test solo per le app che sono cambiate.
- Test del fumo per PR: eseguire un piccolo sottoinsieme (percorso critico) sui PR. Esegui la suite completa su Main.
8. Conclusione
Il test automatizzato non è un “lavoro extra”. È il lavoro. È la differenza tra un prototipo e un prodotto. È la differenza tra “spero che funzioni” e “so che funziona”. Inizia oggi. Scrivi UN test. Il test di accesso. Quindi il test di verifica. Presto dormirai meglio la notte.
Le uscite causano panico?
Progettiamo suite di test E2E automatizzate utilizzando Playwright che rilevano i bug prima che lo facciano gli utenti.