Se ho un codice che ha una copertura del test dell'80% (tutti i test superano), è giusto dire che è di qualità superiore rispetto al codice senza copertura del test?
O è giusto dire che è più mantenibile?
Se ho un codice che ha una copertura del test dell'80% (tutti i test superano), è giusto dire che è di qualità superiore rispetto al codice senza copertura del test?
O è giusto dire che è più mantenibile?
Risposte:
In senso stretto, non è corretto fare affermazioni fino a quando non viene stabilita la qualità della suite di test. Il superamento del 100% dei test non è significativo se la maggior parte dei test sono banali o ripetitivi tra loro.
La domanda è: nella storia del progetto, qualcuno di questi test ha scoperto bug? L'obiettivo di un test è trovare bug. E se non lo facessero, avrebbero fallito come test. Invece di migliorare la qualità del codice, potrebbero darti solo un falso senso di sicurezza.
Per migliorare i progetti di test, è possibile utilizzare (1) tecniche di whitebox, (2) tecniche di blackbox e (3) test di mutazione.
(1) Ecco alcune buone tecniche di whitebox da applicare ai progetti di test. Un test whitebox è costruito tenendo presente il codice sorgente specifico. Un aspetto importante del test della whitebox è la copertura del codice:
if
o while
), hai un test che lo costringe a essere vero e altro che lo costringe a essere falso? [Copertura delle decisioni]&&
) o disgiunzione (usi ||
), ogni sottoespressione ha un test in cui è vero / falso? [Copertura condizioni]break
coperto da un anello?(2) Le tecniche di Blackbox vengono utilizzate quando i requisiti sono disponibili, ma il codice stesso non lo è. Questi possono portare a test di alta qualità:
(3) Infine, supponiamo che abbiate già molti bei test per la copertura del whitebox e le tecniche applicate per il blackbox. Cos'altro puoi fare? È tempo di testare i tuoi test . Una tecnica che puoi utilizzare è il test di mutazione.
Sotto test di mutazione, fai una modifica a (una copia di) il tuo programma, nella speranza di creare un bug. Una mutazione potrebbe essere:
Cambia un riferimento di una variabile in un'altra variabile; Inserisci la funzione abs (); Cambia da meno di a maggiore di; Elimina una dichiarazione; Sostituisci una variabile con una costante; Elimina un metodo di sostituzione; Elimina un riferimento a un metodo super; Cambia l'ordine degli argomenti
Crea diverse decine di mutanti, in vari punti del tuo programma [il programma dovrà ancora essere compilato per testare]. Se i tuoi test non trovano questi bug, ora devi scrivere un test in grado di trovare il bug nella versione mutata del tuo programma. Una volta che un test trova il bug, hai ucciso il mutante e puoi provarne un altro.
Addendum : ho dimenticato di menzionare questo effetto: i bug tendono a raggrupparsi . Ciò significa che più bug trovi in un modulo, maggiore è la probabilità che troverai più bug. Quindi, se hai un test che fallisce (vale a dire, il test ha esito positivo, poiché l'obiettivo è trovare i bug), non solo dovresti correggere il bug, ma dovresti anche scrivere più test per il modulo, usando il tecniche sopra.
Finché trovi bug a un ritmo costante, gli sforzi di test devono continuare. Solo quando si verifica un calo del tasso di nuovi bug rilevati, si dovrebbe avere la certezza di aver compiuto buoni sforzi di test per quella fase di sviluppo.
Secondo una definizione è più mantenibile, poiché ogni cambiamento di rottura ha maggiori probabilità di essere colto dai test.
Tuttavia, il fatto che il codice superi i test unitari non significa che sia intrinsecamente di qualità superiore. Il codice potrebbe ancora essere formattato in modo errato con commenti irrilevanti e strutture dati inadeguate, ma può comunque superare i test.
So quale codice preferirei mantenere ed estendere.
Il codice senza test può essere di qualità estremamente elevata, leggibile, bello ed efficiente (o spazzatura totale), quindi no, non è corretto affermare che un codice con copertura del test dell'80% sia di qualità superiore rispetto al codice senza copertura del test.
Potrebbe essere corretto affermare che il codice coperto per l'80% con buoni test è probabilmente di qualità accettabile e probabilmente relativamente mantenibile. Ma garantisce poco, davvero.
Lo definirei più refattorabile. Il refactoring diventa estremamente semplice se il codice è coperto da molti test.
Sarebbe giusto chiamarlo più mantenibile.
Concordo sulla parte mantenibile. Michael Feathers ha recentemente pubblicato un video di un suo eccellente discorso chiamato " La profonda sinergia tra testabilità e buon design " in cui discute questo argomento. Nel discorso dice che la relazione è un modo, cioè il codice che è ben progettato è testabile, ma il codice verificabile non è necessariamente ben progettato.
Vale la pena notare che lo streaming video non è eccezionale nel video, quindi potrebbe valere la pena scaricarlo se si desidera guardarlo per intero.
Mi pongo questa domanda da qualche tempo in relazione alla "copertura delle condizioni". Che ne dici di questa pagina di atollic.com "Perché l'analisi della copertura del codice?"
Più tecnicamente, l'analisi della copertura del codice trova aree del programma che non sono coperte dai casi di test, consentendo di creare test aggiuntivi che coprono parti del programma altrimenti non testate. È quindi importante comprendere che la copertura del codice consente di comprendere la qualità delle procedure di test, non la qualità del codice stesso .
Questo sembra essere abbastanza rilevante qui. Se hai un set di casi di test che riesce a raggiungere un certo livello di (codice o altro) di copertura, molto probabilmente stai invocando il codice in prova con un insieme piuttosto esaustivo di valori di input! Questo non ti dirà molto sul codice in prova (a meno che il codice non esploda o generi errori rilevabili) ma ti dia fiducia nel set di casi di test .
In un'interessante modifica del Necker Cube , il codice di test è ora in fase di test da parte del codice in prova!
Esistono molti modi per garantire che un programma faccia ciò che si intende e per garantire che le modifiche non abbiano effetti indesiderati.
Il test è uno. Evitare la mutazione dei dati è un altro. Quindi è un sistema di tipi. O verifica formale.
Pertanto, anche se concordo sul fatto che i test sono generalmente positivi, una determinata percentuale di test potrebbe non significare molto. Preferirei fare affidamento su qualcosa scritto in Haskell senza test piuttosto che su una libreria PHP ben collaudata