Vai al contenuto
SDETRole
SDETRole

Glossario · Fondamenti del testing

Mutation testing

Detto anche: test di mutazione, analisi delle mutazioni, mutation score, mutation analysis

Definizione

Tecnica che inserisce nel codice piccoli bug deliberati (mutanti) e riesegue i test per misurare se la suite rileva davvero i difetti.

Il mutation testing (test di mutazione) mette alla prova i tuoi test. Uno strumento crea molte copie del codice, ognuna con una piccola modifica, ad esempio >= trasformato in >, + in -, oppure il corpo di un metodo sostituito con return null. Ogni copia modificata è un mutante. La suite di test viene eseguita contro ogni mutante. Se almeno un test fallisce, il mutante è ucciso (killed). Se tutti i test passano comunque, il mutante è sopravvissuto (survived): significa che i test non si accorgerebbero di quel bug.

Mutation score = mutanti uccisi / mutanti totali (esclusi i mutanti equivalenti).

Esempio

boolean isAdult(int age) {
    return age >= 18;
}

Test: isAdult(30) è true, isAdult(10) è false. La copertura di righe e di branch è al 100%.

Lo strumento crea un mutante con age > 18. Entrambi i test passano ancora, quindi il mutante sopravvive. Questo rivela un test sul valore limite mancante: nessuno ha verificato isAdult(18). Aggiungerlo uccide il mutante. La coverage non poteva dirtelo; il mutation testing sì.

Strumenti

  • Java: PIT (pitest), con plugin per Maven e Gradle e supporto a JUnit 5.
  • JavaScript/TypeScript: StrykerJS, che esiste anche in versione .NET e Scala.
  • Python: mutmut e Cosmic Ray.

Limiti pratici

  • Costo. Ogni mutante è un’esecuzione dei test. Gli strumenti riducono il costo eseguendo solo i test che coprono la riga mutata e lavorando in modo incrementale sul codice modificato, ma resta comunque molto più lento di un’esecuzione normale. La maggior parte dei team lo esegue di notte o sui file modificati in una pull request, non a ogni commit sull’intera codebase.
  • Mutanti equivalenti. Alcune modifiche non alterano affatto il comportamento, ad esempio trasformare i < n in i != n in un ciclo in cui i cresce sempre di uno partendo da un valore inferiore a n. Nessun test può ucciderli, quindi vanno analizzati ed esclusi a mano.
  • Dà il meglio a livello unit. Il mutation testing è pensato per unit test veloci e deterministici. Eseguirlo su test UI lenti raramente è praticabile.

Usa i mutanti sopravvissuti come lista di cose da fare per le asserzioni mancanti, soprattutto nella logica di business, invece di inseguire un punteggio perfetto.

Scrivi per cercare in tutto SDETRole.

Ricerca full-text con Pagefind · funziona nel tuo browser Apri la pagina di ricerca →