"Abbiamo il 95% di code coverage." Bene. Ma il test coverage 100% è davvero l'obiettivo giusto? Cosa stiamo davvero testando? Mi è capitato di vedere suite di test con coverage altissima che non intercettavano bug critici in produzione. E suite con coverage molto basse che coprivano i flussi che contavano davvero.
La code coverage rischia di diventare una metrica fine a se stessa. Un numero da mostrare nelle dashboard, da mettere nei badge del repository, da esibire nelle code review. Un numero alto non dice nulla sulla qualità dei test. Dice solo che del codice è stato eseguito durante i test.
Perché la coverage è una metrica ingannevole
Coverage misura l'esecuzione, non la verifica
Se scrivo un test che chiama una funzione ma non verifica il risultato, la coverage aumenta. La funzione è stata “coperta”: il codice è stato eseguito. Ma il test non protegge nulla. Il test passa, la coverage sale, e il bug resta lì.
I test facili alzano i numeri, quelli difficili salvano il prodotto
Testare un getter che restituisce un campo è facile. La coverage aumenta. Testare il flusso di pagamento completo con gestione degli errori, retry, e rollback è difficile. Aggiunge poca coverage, ma è il test che ti salva quando qualcosa va storto.
La tendenza naturale è scrivere molti test facili, veloci da scrivere e utili ad alzare la metrica, e pochi test difficili che richiedono setup e ragionamento. Il risultato è una suite che dà una falsa sensazione di sicurezza.
Il 100% è un obiettivo che raramente ha senso economico
Passare dal 70% all’80% è relativamente economico. Dall’80% al 90% lo sforzo cresce in modo significativo. Dal 90% al 100% lo sforzo tende a diventare sproporzionato rispetto al valore aggiunto.
Quell’ultimo tratto include casi molto rari che difficilmente vedrai in produzione. Il tempo che il team spende a inseguire il 100% è tempo che non spende a testare i flussi critici in modo più approfondito.
Quali test servono davvero
I flussi che fanno guadagnare soldi
Registrazione, login, pagamento, le azioni core del tuo prodotto. Se questi si rompono, perdi utenti e ricavi. Testali in modo approfondito: happy path, errori comuni, casi limite realistici e integrazioni reali.
Pochi test ben scritti qui valgono più di molti test su utilità secondarie.
Le integrazioni con sistemi esterni
API di terze parti, gateway di pagamento, servizi di email, storage — tutto ciò che è fuori dal tuo controllo. Qui è dove le cose tendono a rompersi più spesso: API che cambiano, timeout diversi, formati non documentati.
I test di integrazione che verificano il comportamento reale — non mock — sono tra i più preziosi che puoi avere.
I casi che ti fanno perdere soldi
Un utente viene addebitato due volte? Un ordine viene perso? I dati personali finiscono esposti? Questi scenari hanno un costo sproporzionato rispetto alla loro frequenza. Un test che previene un doppio addebito può valere più di decine di test su logica secondaria.
Identifica gli scenari più rischiosi per il tuo business e dedica particolare attenzione a testarli.
Le regressioni dopo ogni bug in produzione
Ogni bug significativo che arriva in produzione dovrebbe generare un test. Non per coverage — per prevenzione. Se è successo una volta, può succedere di nuovo. Il test riduce significativamente la probabilità che si ripresenti.
Nel tempo, questa pratica costruisce una suite che copre i problemi reali del tuo prodotto. Ed è anche ciò che rende possibile il refactoring sicuro invece della riscrittura da zero.
Cosa dire al team (e al PM)
Se gestisci un team e la coverage è diventata un obiettivo:
Non fissare target di coverage. Un target del 90% rischia di incentivare test scritti per alzare il numero più che per proteggere il prodotto. Incentiva la copertura dei flussi critici. È molto più utile di un “90% coverage”.
Chiedi "cosa testa?" non "quanta coverage?" Quando il team aggiunge test, la domanda è: quale scenario stiamo prevenendo? Se la risposta è “alza la coverage”, quel test probabilmente non serve.
Metti a budget il tempo per i test giusti. I test di integrazione richiedono più tempo da scrivere e da manutenere. Se il team è sotto pressione per rispettare stime, i test che tendono a essere tagliati per primi sono quelli complessi — cioè quelli che servono di più.
Misura i bug in produzione, non la coverage. La metrica che conta è: quanti bug arrivano in produzione.
Il testing è un investimento, non una cerimonia
I test sono codice. Vanno scritti, mantenuti, eseguiti, e ogni tanto riscritti. Sono un costo — un costo che si ripaga prevenendo problemi più costosi. Ma solo se testano le cose giuste. Senza una buona suite di test sui flussi critici, il deploy diventa una roulette e il team finisce per avere paura di rilasciare.
Un team con il 40% di coverage concentrata sui flussi critici è spesso in una posizione più solida di un team con il 95% distribuita uniformemente su codice che non ha impatto diretto sul business.
La coverage è un indicatore, non l’obiettivo. I test servono a proteggere il prodotto, non a riempire una metrica. L’obiettivo è un prodotto che continua a funzionare anche quando il codice cambia.
Se vuoi capire se la tua suite di test sta proteggendo il tuo business o sta solo alzando un numero in una dashboard, parliamone. Un'analisi mirata può rivelare i punti scoperti che la coverage non vede.
Simone Giusti
Full Stack Developer specializzato in Laravel e Vue.js



