Domanda

La copertura del codice è probabilmente la metrica del codice più controversa. Alcuni dicono che devi raggiungere l'80% di copertura del codice, altri dicono che è superficiale e non dice nulla sulla qualità dei test. (Vedi la buona risposta di Jon Limjap su " Qual è una percentuale di codice ragionevole per i test unitari (e perché)? " .)

Le persone tendono a misurare tutto. Hanno bisogno di confronti, parametri di riferimento ecc.
I team di progetto hanno bisogno di un puntatore, quanto è buono il loro test.

Quindi quali sono le alternative alla copertura del codice? Quale sarebbe una buona metrica che dice più di & Quot; Ho toccato questa riga di codice & Quot ;?
Ci sono alternative reali?

È stato utile?

Soluzione

Se stai cercando alcune metriche utili che ti raccontano la qualità (o la mancanza di) del tuo codice, dovresti esaminare le seguenti metriche:

  1. Complessità ciclomatica
    • Questa è una misura di quanto sia complesso un metodo.
    • Di solito 10 e più basso è buono, 11-25 è scarso, più alto è terribile.
  2. Profondità di annidamento
    • Questa è una misura di quanti ambiti nidificati ci sono in un metodo.
    • Di solito 4 e inferiore sono buoni, 5-8 sono poveri, superiori è terribile.
  3. Coesione relazionale
    • Questa è una misura della relazione tra i tipi in un pacchetto o in un assieme.
    • La coesione relazionale è in qualche modo una metrica relativa, ma utile comunque.
    • I livelli accettabili dipendono dalla formula. Dato quanto segue:
      • R: numero di relazioni nel pacchetto / assembly
      • N: numero di tipi nel pacchetto / assembly
      • H: coesione della relazione tra i tipi
    • Formula: H = (R + 1) / N
    • Data la formula sopra, l'intervallo accettabile è 1,5 - 4,0
  4. Mancanza di coesione dei metodi (LCOM)
    • Questa è una misura della coesione di una classe.
    • La coesione di una classe è una misura di quanti campi fa riferimento a ciascun metodo.
    • Buona indicazione se la tua classe soddisfa il Responsabile della responsabilità singola.
    • Formula: LCOM = 1 - (somma (MF) / M * F)
      • M: numero di metodi nella classe
      • F: numero di campi dell'istanza nella classe
      • MF: numero di metodi in classe che accedono a un determinato campo di istanza
      • sum (MF): la somma di MF su tutti i campi dell'istanza
    • Una classe totalmente coesa avrà una LCOM di 0.
    • Una classe completamente non coesa avrà una LCOM di 1.
    • Più vicino a 0 ti avvicini, più coesa e mantenibile, la tua classe.

Queste sono solo alcune delle metriche chiave che NDepend, una metrica .NET e un'utilità di mappatura delle dipendenze, possono fornirti. Di recente ho lavorato molto con le metriche del codice e queste 4 metriche sono le metriche chiave fondamentali che abbiamo trovato più utili. NDepend offre diverse altre metriche utili, incluso Amper Efferent &; Accoppiamento afferente e astrattezza & Amp; L'instabilità, che combinata fornisce una buona misura di quanto sarà gestibile il tuo codice (e se sei o meno in quello che NDepend chiama la zona di dolore o la zona di inutilità.)

Anche se non lavori con la piattaforma .NET, ti consiglio di dare un'occhiata alla pagina delle metriche NDepend . Ci sono molte informazioni utili lì che potresti essere in grado di utilizzare per calcolare queste metriche su qualsiasi piattaforma su cui sviluppi.

Altri suggerimenti

Crap4j è una metrica abbastanza buona di cui sono a conoscenza ...

È un'implementazione Java della metrica del software di analisi e previsioni del rischio di cambiamento che combina la complessità ciclomatica e la copertura del codice dai test automatizzati.

Anche le metriche dei bug sono importanti:

  • Numero di bug in arrivo
  • Numero di bug risolti

Per rilevare, ad esempio, se i bug non vengono risolti con la stessa velocità con cui arrivano nuovi.

Che ne dici di guardare l'andamento della copertura del codice durante il tuo progetto?

Come nel caso di molte altre metriche, un singolo numero non dice molto.

Ad esempio, è difficile dire se c'è un problema se " abbiamo una conformità alle regole Checkstyle del 78.765432% " ;. Se la conformità di ieri è stata del 100%, siamo sicuramente nei guai. Se ieri fosse il 50%, probabilmente stiamo facendo un buon lavoro.

Sono sempre nervoso quando la copertura del codice è diventata sempre più bassa nel tempo. Ci sono casi in cui va bene, quindi non puoi spegnere la testa quando guardi grafici e numeri.

A proposito, il sonar ( http://sonar.codehaus.org/ ) è un ottimo strumento per guardare le tendenze.

L'uso della copertura del codice da solo è per lo più inutile, ti dà un'idea solo se stai cercando un codice non necessario.

Usandolo insieme ai test unitari e puntando al 100% di copertura, ti dirà che tutte le parti "testate" (supponendo che anche tutte abbiano avuto successo) funzionano come specificato nel test unitario.

Scrivere unit test da un progetto tecnico / funzionale, con una copertura del 100% e test riusciti al 100% ti dirà che il programma funziona come descritto nella documentazione.

Ora l'unica cosa di cui hai bisogno è una buona documentazione, specialmente la progettazione funzionale, un programmatore non dovrebbe scrivere che a meno che non sia un esperto di quel campo specifico.

La copertura del codice è solo un indicatore e aiuta a sottolineare le linee che non vengono eseguite affatto nei test, il che è piuttosto interessante. Se raggiungi circa l'80% di copertura del codice, inizia a dare un'occhiata al restante 20% di righe per identificare se ti manca un caso d'uso. Se vedi & Quot; aha, questa riga viene eseguita se passo un vettore vuoto & Quot; quindi puoi effettivamente scrivere un test che passa un vettore vuoto.

In alternativa, a cui riesco a pensare, se hai un documento di specifiche con Casi d'uso e Requisiti funzionali, dovresti mappare i test unitari su di essi e vedere quanti UC sono coperti da FR (ovviamente dovrebbe essere al 100%) e quanti FR sono coperti da UT (di nuovo, dovrebbe essere al 100%).

Se non hai specifiche, a chi importa? Tutto ciò che accade sarà ok :)

Che ne dici di (righe di codice) / (numero di casi di test)? Non estremamente significativo (poiché dipende da LOC), ma almeno è facile da calcolare.

Un altro potrebbe essere (numero di casi di test) / (numero di metodi).

Copertura dello scenario.

Non penso che tu voglia davvero avere una copertura del codice al 100%. I test dicono che semplici getter e setter sembrano una perdita di tempo.

Il codice viene sempre eseguito in un determinato contesto, quindi è possibile elencare il maggior numero di scenari possibile (a seconda della complessità del problema, a volte anche tutti) e testarli.

Esempio:

// parses a line from .ini configuration file
// e.g. in the form of name=value1,value2
List parseConfig(string setting)
{
    (name, values) = split_string_to_name_and_values(setting, '=')
    values_list = split_values(values, ',')
    return values_list
}

Ora hai molti scenari da testare. Alcuni di essi:

  • Passaggio del valore corretto

  • Voce di elenco

  • Passare null

  • Passando stringa vuota

  • Passaggio di parametri non formattati

  • Passaggio di stringa con virgola iniziale o finale, ad es. nome = valore1 o nome =, valore2

L'esecuzione del primo test può fornire (a seconda del codice) una copertura del codice del 100%. Ma non hai considerato tutte le possibilità, quindi quella metrica da sola non ti dice molto.

Ho scritto un post sul blog sul perché Il rapporto di copertura dei test elevati è comunque una buona cosa .

Sono d'accordo che: quando una parte del codice viene eseguita da test, non & # 8217; t significa che la validità dei risultati prodotti da questa parte di codice viene verificata da test .

Tuttavia, se si utilizzano pesantemente i contratti per verificare la validità degli stati durante l'esecuzione dei test, un'elevata copertura dei test comporterà comunque molte verifiche.

Il valore nella copertura del codice è che ti dà un'idea di ciò che è stato esercitato dai test. La frase & Quot; copertura del codice & Quot; viene spesso utilizzato per indicare la copertura delle istruzioni, ad esempio " la quantità del mio codice (in righe) è stata eseguita " ;, ma in realtà ci sono oltre un centinaio di varietà di " copertura < !> quot ;. Queste altre versioni della copertura cercano di fornire una visione più sofisticata del significato dell'esercizio del codice.

Ad esempio, la copertura delle condizioni misura quanti elementi separati delle espressioni condizionali sono stati esercitati. Questo è diverso dalla copertura delle dichiarazioni. MC / DC " condizioni modificate / copertura decisionale " determina se sono stati dimostrati tutti gli elementi di tutte le espressioni condizionali per controllare l'esito del condizionale ed è richiesto dalla FAA per il software dell'aeromobile. La copertura del percorso misura quanti dei possibili percorsi di esecuzione attraverso il codice sono stati esercitati. Questa è una misura migliore della copertura delle istruzioni, in quanto i percorsi rappresentano essenzialmente diversi casi nel codice. Quale di queste misure è meglio usare dipende da quanto sei preoccupato per l'efficacia dei tuoi test.

Wikipedia discute abbastanza bene di molte varianti della copertura del test. http://en.wikipedia.org/wiki/Code_coverage

Come regola empirica, i tassi di iniezione dei difetti sono proporzionalmente resi in codice trail ed entrambi in genere seguono una curva di distribuzione di Rayleigh.
Ad un certo punto il tasso di rilevamento dei difetti raggiungerà il picco e quindi inizierà a diminuire.
Questo apice rappresenta il 40% dei difetti scoperti.
Andando avanti con una semplice analisi di regressione è possibile stimare quanti difetti rimangono nel prodotto in qualsiasi momento dopo il picco.
Questa è una componente del modello di Lawrence Putnam.

Questo non è stato menzionato, ma la quantità di modifiche in un determinato file di codice o metodo (osservando la cronologia del controllo versione) è interessante in particolare quando si crea una suite di test per codice scarsamente testato. Concentrare i test sulle parti del codice che si modificano molto. Lascia quelli che non farai più tardi.

Fai attenzione a un'inversione di causa ed effetto. Potresti evitare di modificare il codice non testato e potresti tendere a cambiare di più il codice testato.

SQLite è una estremamente ben testata e puoi estrarre da esso tutti i tipi di metriche.

  

A partire dalla versione 3.6.14 (tutte le statistiche nel report sono contro quella versione di SQLite), la libreria SQLite è composta da circa 63,2 KSLOC di codice C. (KSLOC significa migliaia di & Quot; Source Lines Of Code & Quot; o, in altre parole, righe di codice esclusi righe vuote e commenti.) In confronto, il progetto ha 715 volte più codice di test e script di test - 45261,5 KSLOC.

Alla fine, ciò che mi colpisce sempre come il più significativo è che nessuna di quelle possibili metriche sembra essere importante quanto la semplice dichiarazione, " soddisfa tutti i requisiti. " (Quindi non perdere di vista tale obiettivo nel processo di raggiungimento.)

Se vuoi qualcosa per giudicare i progressi di una squadra, devi stabilire i requisiti individuali. Questo ti dà qualcosa su cui puntare e dire & Quot; questo è fatto, questo non è & Quot ;. Non è lineare (la risoluzione di ogni requisito richiederà un lavoro variabile) e l'unico modo per linearizzare è se il problema è già stato risolto altrove (e quindi è possibile quantizzare il lavoro per requisito).

Mi piacciono le entrate, i numeri di vendita, i profitti. Sono metriche abbastanza buone di una base di codice.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top