Qual è una percentuale di codice ragionevole per i test unitari (e perché)? [chiuso]


605

Se dovessi imporre una copertura minima del codice percentuale per i test unitari, forse anche come requisito per impegnarsi in un repository, quale sarebbe?

Per favore, spiega come sei arrivato alla tua risposta (dato che se tutto ciò che facevi fosse scegliere un numero, avrei potuto farlo da solo;)


Ora un giorno molti IDE vengono con l'evidenziazione della copertura, assicurati di coprire le parti più importanti del codice almeno che pensare di raggiungere una determinata percentuale.
Tutto vistosamente il

4
Il simbolo% è odore di codice per le metriche (anche% è un odore di cazzate in generale)
Hernán Eche

I test unitari per definizione possono essere singoli metodi, intere classi o interi moduli. Anche se testerai tutti i metodi, potresti non testare tutti i percorsi o tutte le combinazioni che un utente colpirà. La situazione diventa più complessa con dichiarazioni, copertura delle filiali e MCDC.
Ska

Perché questa domanda non viene cancellata o modificata correttamente. Ha raccolto così tanto interesse ma è totalmente fuorviante.
Ska,

Risposte:


1391

Questa prosa di Alberto Savoia risponde proprio a questa domanda (in modo piacevolmente divertente!):

http://www.artima.com/forums/flat.jsp?forum=106&thread=204677

Testivus sulla copertura del test

Una mattina presto, un programmatore chiese al grande maestro:

“Sono pronto a scrivere alcuni test unitari. Quale copertura del codice dovrei puntare? ”

Il grande maestro rispose:

"Non preoccuparti della copertura, basta scrivere alcuni buoni test."

Il programmatore sorrise, si inchinò e se ne andò.

...

Più tardi quel giorno, un secondo programmatore fece la stessa domanda.

Il grande maestro indicò una pentola di acqua bollente e disse:

"Quanti chicchi di riso dovrei mettere in quella pentola?"

Il programmatore, sembrando perplesso, rispose:

“Come posso dirtelo? Dipende da quante persone devi nutrire, da quanto hanno fame, da quale altro cibo stai servendo, da quanto riso hai a disposizione e così via. ”

"Esatto", disse il grande maestro.

Il secondo programmatore sorrise, si inchinò e se ne andò.

...

Verso la fine della giornata, arrivò un terzo programmatore e fece la stessa domanda sulla copertura del codice.

"L'ottanta percento e non meno!" Rispose il maestro con voce severa, battendo il pugno sul tavolo.

Il terzo programmatore sorrise, si inchinò e se ne andò.

...

Dopo quest'ultima risposta, un giovane apprendista si avvicinò al grande maestro:

“Grande maestro, oggi ho sentito per caso rispondere alla stessa domanda sulla copertura del codice con tre risposte diverse. Perché?"

Il grande maestro si alzò dalla sua sedia:

"Vieni a prendere un po 'di tè fresco con me e parliamone."

Dopo aver riempito le tazze con il fumo del tè verde caldo, il grande maestro iniziò a rispondere:

“Il primo programmatore è nuovo e ha appena iniziato i test. In questo momento ha un sacco di codice e nessun test. Ha una lunga strada da percorrere; concentrarsi sulla copertura del codice in questo momento sarebbe deprimente e del tutto inutile. Sta meglio solo abituarsi a scrivere ed eseguire alcuni test. Può preoccuparsi della copertura più tardi. "

“Il secondo programmatore, d'altra parte, è abbastanza esperto sia nella programmazione che nei test. Quando le ho risposto chiedendole quanti chicchi di riso dovevo mettere in una pentola, l'ho aiutata a capire che la quantità di prove necessarie dipende da una serie di fattori e lei conosce quei fattori meglio di me - dopo tutto è il suo codice . Non esiste una risposta singola, semplice, ed è abbastanza intelligente da gestire la verità e lavorare con quella ".

"Capisco", disse il giovane apprendista, "ma se non c'è una sola risposta semplice, allora perché hai risposto al terzo programmatore" Ottanta per cento e non meno "?"

Il grande maestro rise così forte e forte che il suo ventre, la prova che aveva bevuto più di un semplice tè verde, cadde su e giù.

"Il terzo programmatore vuole solo risposte semplici, anche quando non ci sono risposte semplici ... e poi non le segue comunque."

Il giovane apprendista e il grande maestro brizzolato finirono di bere il loro tè in silenzio contemplativo.


62
Sembra un argomento contro il concetto generale di copertura del codice, come metrica per valutare l'utilità dei test unitari. Sono sicuro che tutti concordano sul fatto che non è una metrica perfetta, ma l'esperienza personale dovrebbe sperare di mostrare una correlazione tra CC% ed efficacia del test unitario ...
sanità mentale

16
sanità mentale - la tua affermazione è rispecchiata proprio dalla risposta al "secondo sviluppatore". L'esperienza personale dovrebbe dettarla.
Jon Limjap,

167
Risposta perfetta Le metriche non creano un buon codice. Puoi scrivere codice scadente con una copertura del 100% e non funziona bene. +1 da parte mia, peccato che non riesca ad aumentare di più :)
Rob Cooper,

15
4 anni dopo, e ancora utile. Ho appena parlato con due miei colleghi stamattina.
SickHippie,

9
Per me questo aneddoto rappresenta una visione idealistica. Nel mondo reale dei team di progetto con priorità in competizione, la copertura del codice corre allo 0%. Abbiamo bisogno di un numero richiesto per creare l'abitudine di test unitari all'interno del team. Sono arrivato a questa domanda cercando una guida per determinare quel numero per un'area che non conosco molto bene, e questo non è davvero di alcun aiuto. Sono contento che le persone in altri scenari lo trovino utile.
samspot

85

La copertura del codice è una metrica fuorviante se il tuo obiettivo è una copertura del 100% (anziché test al 100% di tutte le funzionalità).

  • Puoi ottenere un 100% colpendo tutte le linee una volta. Tuttavia, potresti ancora perdere il test di una particolare sequenza (percorso logico) in cui vengono colpite quelle linee.
  • Non è stato possibile ottenere un 100%, ma sono ancora stati testati tutti i percorsi di codice utilizzati all'80% / freq. Avere test che testano ogni "lancio ExceptionTypeX" o simile protezione di programmazione difensiva che hai inserito è un "bello avere" non un "must have"

Quindi fidati di te o dei tuoi sviluppatori per essere accurati e coprire ogni percorso attraverso il loro codice. Sii pragmatico e non inseguire la magica copertura del 100%. Se TDD il tuo codice dovresti ottenere una copertura del 90% + come bonus. Usa la copertura del codice per evidenziare pezzi di codice che hai perso (non dovrebbe accadere se TDD però .. dato che scrivi il codice solo per fare un passaggio di test. Nessun codice può esistere senza il suo test partner.)


4
- Eccezioni: se non si verifica la gestione delle eccezioni, come si fa a sapere se il codice non viene espulso quando ciò accade? - Setter / Getters - sensibile al contesto, suppongo, ma sicuramente i tuoi test dovrebbero eseguirli come parte della suite di test, e se non lo sono vengono effettivamente utilizzati?
tddmonkey,

1
Le eccezioni dovrebbero essere eccezionali, non dovrebbero accadere. In tal caso, si registra il punto di errore e la cauzione. Non puoi testare ogni eccezione che potrebbe accadere. Se l'app deve gestire un percorso / evento non felice, dovresti sottoporti a un test. Gli accessori possono essere aggiunti per i futuri clienti .. dipende
Gishu

5
Non sono sicuro di cosa intendi con il tuo secondo punto "ma ho ancora testato tutti i tuoi percorsi di codice". Se in realtà si intende una copertura per l'intero percorso, no, non è possibile avere una copertura per l'intero percorso senza copertura al 100% di linea / ramo / decisione. In effetti, la copertura del percorso completo è generalmente impossibile da ottenere in qualsiasi programma non banale a causa della natura combinatoria dei rami nel generare percorsi. en.wikipedia.org/wiki/Code_coverage#Other_coverage_criteria
Zach Burlingame

3
Non testare ogni possibile eccezione; certo che non puoi farlo. Dovresti mirare a testare ogni blocco di codice che gestisce le eccezioni. Ad esempio, se hai il requisito che quando il blocco X genera un'eccezione, l'eccezione viene registrata nel database, la striscia verde nella parte inferiore dello schermo diventa rossa e viene inviata un'email al Papa; allora questo è ciò che dovresti testare. Ma non devi testare tutte le possibili eccezioni che potrebbero innescare questi eventi.
Dawood ibn Kareem,

2
+1 per "Usa la copertura del codice per evidenziare blocchi di codice che hai perso". Questo è fondamentalmente il motivo per cui questa metrica è utile.
Beluchin,

61

La copertura del codice è ottima, ma la copertura delle funzionalità è ancora migliore. Non credo nel coprire ogni singola riga che scrivo. Ma credo nello scrivere una copertura di prova al 100% di tutte le funzionalità che voglio fornire (anche per le straordinarie funzionalità che sono venuto con me stesso e che non sono state discusse durante le riunioni).

Non mi importa se avrei un codice che non è coperto dai test, ma mi piacerebbe se rifattassi il mio codice e finissi per avere un comportamento diverso. Pertanto, la copertura di funzionalità al 100% è il mio unico obiettivo.


4
Questa è una risposta fantastica Il codice che soddisfa i suoi requisiti è un obiettivo molto più utile del codice che soddisfa alcune metriche di copertura LoC arbitrarie.
Dawood ibn Kareem,

46
Se puoi fornire tutte le funzionalità senza colpire tutte le righe di codice, allora cosa ci fanno quelle righe di codice in più?
Jens Timmerman,

4
@JensTimmerman teoricamente hai ragione. Tuttavia, la copertura del codice al 100% è troppo dispendiosa in termini di tempo e costringere il mio team a farlo non solo li demotiva, ma rende anche il mio progetto scaduto. Mi piace essere da qualche parte nel mezzo e testare la funzionalità (chiamalo: test di integrazione) è ciò con cui mi sento a mio agio. Quale codice non testare? Gestione delle eccezioni tecniche, controlli (intervallo / parametro) che potrebbero essere necessari. In breve, tutto l'impianto idraulico tecnico che ho imparato ad applicare dalla mia esperienza o dalle migliori pratiche di cui ho letto.
tofi9,

2
Ho fatto un ulteriore passo avanti facendo un elenco di situazioni comuni che dovrebbero essere incluse o escluse dai test. In questo modo, non abbiamo mai guidato verso una percentuale, ma piuttosto una copertura funzionale di tutte le parti della base di codice funzionante.
Skeeterdrums,

58

La risposta accettata ha un buon punto: non esiste un solo numero che abbia senso come standard per ogni progetto. Ci sono progetti che non hanno bisogno di un tale standard. Dove la risposta accettata non è all'altezza, secondo me, è nel descrivere come si potrebbe prendere quella decisione per un determinato progetto.

Ci proverò a farlo. Non sono un esperto in ingegneria di test e sarei felice di vedere una risposta più informata.

Quando impostare i requisiti di copertura del codice

Innanzitutto, perché dovresti voler imporre un tale standard in primo luogo? In generale, quando si desidera introdurre fiducia empirica nel proprio processo. Cosa intendo per "fiducia empirica"? Bene, la vera correttezza dell'obiettivo . Per la maggior parte dei software, non possiamo assolutamente saperlo su tutti gli input, quindi ci accontentiamo di dire che il codice è ben testato . Questo è più conoscibile, ma è ancora uno standard soggettivo: sarà sempre aperto a discutere se lo hai incontrato o meno. Questi dibattiti sono utili e dovrebbero verificarsi, ma espongono anche incertezza.

La copertura del codice è una misurazione oggettiva: una volta visualizzato il report di copertura, non vi è alcuna ambiguità sul fatto che gli standard siano stati soddisfatti siano utili. Dimostra la correttezza? Niente affatto, ma ha una chiara relazione con quanto è ben testato il codice, che a sua volta è il nostro modo migliore per aumentare la fiducia nella sua correttezza. La copertura del codice è un'approssimazione misurabile delle qualità incommensurabili a cui teniamo.

Alcuni casi specifici in cui avere uno standard empirico potrebbe aggiungere valore:

  • Per soddisfare le parti interessate. Per molti progetti, ci sono vari attori interessati alla qualità del software che potrebbero non essere coinvolti nello sviluppo quotidiano del software (gestori, lead tecnici, ecc.) Dicendo "scriveremo tutti i i test di cui abbiamo veramente bisogno "non sono convincenti: entrambi devono fidarsi del tutto o verificare con una stretta supervisione in corso (supponendo che abbiano anche la comprensione tecnica per farlo.) Fornire standard misurabili e spiegare come essi ragionevolmente approssimano gli obiettivi reali è meglio.
  • Per normalizzare il comportamento della squadra. A parte gli stakeholder, se stai lavorando in un team in cui più persone scrivono codice e test, c'è spazio per l'ambiguità per ciò che si qualifica come "ben collaudato". Tutti i tuoi colleghi hanno la stessa idea di quale livello di test è abbastanza buono? Probabilmente no. Come si concilia questo? Trova una metrica su cui puoi essere tutti d'accordo e accettala come approssimazione ragionevole. Ciò è particolarmente (ma non esclusivamente) utile nei team di grandi dimensioni, dove i lead potrebbero non avere una supervisione diretta sugli sviluppatori junior, ad esempio. Anche le reti di fiducia contano, ma senza misurazioni oggettive, è facile che il comportamento del gruppo diventi incoerente, anche se tutti agiscono in buona fede.
  • Per essere onesto. Anche se sei l'unico sviluppatore e unico stakeholder per il tuo progetto, potresti avere in mente alcune qualità per il software. Invece di fare valutazioni soggettive in corso su quanto sia ben collaudato il software (che richiede lavoro), è possibile utilizzare la copertura del codice come approssimazione ragionevole e lasciare che le macchine lo misurino per te.

Quali metriche usare

La copertura del codice non è una singola metrica; ci sono diversi modi per misurare la copertura. Quale su cui potresti impostare uno standard dipende da cosa stai usando quello standard per soddisfare.

Userò due metriche comuni come esempi di quando potresti usarle per stabilire degli standard:

  • Copertura delle dichiarazioni : quale percentuale di dichiarazioni è stata eseguita durante i test? Utile per avere un'idea della copertura fisica del tuo codice: quanto del codice che ho scritto ho effettivamente testato?
    • Questo tipo di copertura supporta un argomento di correttezza più debole, ma è anche più facile da raggiungere. Se stai semplicemente utilizzando la copertura del codice per assicurarti che le cose vengano testate (e non come indicatore della qualità del test oltre a quello), probabilmente la copertura delle dichiarazioni è sufficiente.
  • Copertura dei rami : quando esiste una logica di ramificazione (ad es. Un if), sono stati valutati entrambi i rami? Questo dà un migliore senso della copertura logica del tuo codice: quanti dei possibili percorsi che il mio codice potrebbe seguire sono stati testati?
    • Questo tipo di copertura è un indicatore molto migliore che un programma è stato testato attraverso una serie completa di input. Se si utilizza la copertura del codice come migliore approssimazione empirica per la fiducia nella correttezza, è necessario stabilire standard basati sulla copertura delle filiali o simili.

Esistono molte altre metriche (la copertura delle linee è simile alla copertura delle dichiarazioni, ma produce risultati numerici diversi per le dichiarazioni multilinea, ad esempio; la copertura condizionale e la copertura del percorso sono simili alla copertura delle filiali, ma riflettono una visione più dettagliata delle possibili permutazioni di esecuzione del programma che potresti riscontrare.)

Quale percentuale richiedere

Infine, torniamo alla domanda originale: se imposti gli standard di copertura del codice, quale dovrebbe essere quel numero?

Spero che a questo punto sia chiaro che stiamo parlando di un'approssimazione, quindi qualsiasi numero che prendiamo sarà intrinsecamente approssimativo.

Alcuni numeri che si potrebbero scegliere:

  • 100% . Puoi scegliere questo perché vuoi essere sicuro che tutto sia testato. Questo non ti dà un'idea della qualità del test, ma ti dice che alcuni test di una certa qualità hanno toccato ogni affermazione (o ramo, ecc.) Ancora una volta, questo torna al grado di fiducia: se la tua copertura è inferiore al 100% , sai che un sottoinsieme del tuo codice non è testato.
    • Alcuni potrebbero obiettare che questo è stupido e dovresti testare solo le parti del tuo codice che sono davvero importanti. Direi che dovresti anche mantenere solo le parti del tuo codice che sono davvero importanti. La copertura del codice può essere migliorata rimuovendo anche il codice non testato.
  • 99% (o 95%, altri numeri negli anni '90). Adatto nei casi in cui si desidera trasmettere un livello di confidenza simile al 100%, ma lasciare un margine per non preoccuparsi dell'angolo occasionale difficile da testare di codice.
  • 80% . Ho visto questo numero in uso alcune volte e non so del tutto da dove provenga. Io penso che potrebbe essere un'appropriazione indebita strana della regola 80-20; in genere, l'intento qui è mostrare che la maggior parte del codice è stata testata. (Sì, il 51% sarebbe anche "la maggior parte", ma l'80% rispecchia maggiormente ciò che la maggior parte delle persone intende per maggior parte.) Questo è appropriato per i casi di medio livello in cui "ben testato" non è una priorità (non non voglio sprecare sforzi in test di basso valore), ma è abbastanza prioritario che ti piacerebbe avere ancora qualche standard in atto.

In pratica non ho visto numeri inferiori all'80% e faccio fatica a immaginare un caso in cui si potrebbero impostare. Il ruolo di questi standard è aumentare la fiducia nella correttezza e numeri inferiori all'80% non sono particolarmente stimolanti. (Sì, questo è soggettivo, ma ancora una volta l'idea è di fare una scelta soggettiva quando si imposta lo standard e quindi utilizzare una misurazione obiettiva per il futuro.)

Altre note

Quanto sopra presuppone che l'obiettivo sia la correttezza. La copertura del codice è solo informazione; potrebbe essere rilevante per altri obiettivi. Ad esempio, se sei preoccupato per la manutenibilità, probabilmente ti preoccupi dell'accoppiamento libero, che può essere dimostrato dalla testabilità, che a sua volta può essere misurato (in alcune mode) dalla copertura del codice. Quindi il tuo standard di copertura del codice fornisce una base empirica per approssimare anche la qualità della "manutenibilità".


Buona risposta. Potete aiutarmi a trovare la copertura della funzionalità tramite unit test? Qualche strumento / i che può aiutarmi a raggiungere questo obiettivo?
Curlyreggie

2
Bella risposta. È l'unico che si concentra sui test come problema di squadra in un ambiente industriale. Non riesco a recensire tutto e la mia squadra è molto brillante, ma verde. Ho fissato una percentuale del 90% su un nuovo progetto come controllo di integrità per gli sviluppatori junior, non perché credo che sia "sufficiente". "90%" e "positivo, negativo e nullo" sono mantra facili per i giovani sviluppatori brillanti che conosco faranno un buon lavoro, ma non hanno l'esperienza per andare avanti e scrivere quel caso di test extra che è fastidioso al ripensamento.
0x1,

2
penso che questa sia la migliore risposta disponibile.
bugkiller,

27

La mia copertura di codice preferita è al 100% con un asterisco. L'asterisco viene perché preferisco usare strumenti che mi consentono di contrassegnare determinate linee come linee che "non contano". Se ho coperto il 100% delle righe che "contano", ho finito.

Il processo sottostante è:

  1. Scrivo i miei test per esercitare tutte le funzionalità e i casi limite che mi vengono in mente (di solito lavorando dalla documentazione).
  2. Corro gli strumenti di copertura del codice
  3. Esamino le linee o i percorsi non coperti e quelli che ritengo non importanti o irraggiungibili (a causa di una programmazione difensiva) che contrassegno come non conteggi
  4. Scrivo nuovi test per coprire le righe mancanti e migliorare la documentazione se questi casi limite non sono menzionati.

In questo modo se io e i miei collaboratori aggiungiamo un nuovo codice o modifichiamo i test in futuro, c'è una linea chiara per dirci se abbiamo perso qualcosa di importante: la copertura è scesa al di sotto del 100%. Tuttavia, offre anche la flessibilità necessaria per gestire diverse priorità di test.


3
@ErikE Asterix è, ovviamente, un breve ma impavido guerriero della Gallia che crea eccezioni alla monotona occupazione romana e quindi il piccolo simbolo tipografico che segnala le eccezioni prende il nome da lui. (Più seriamente, grazie, ho corretto l'ortografia.)
Eponimo

3
Ti andrebbe di includere gli "strumenti che consentono a [tu] di contrassegnare determinate linee come linee che non contano"?
domdambrogia,

2
@domdambrogia Come esempio in PHP, se si utilizza la libreria di copertura codici Bergmann, annotare una riga con // @codeCoverageIgnoree verrà esclusa dalla copertura.
vescovo,

19

Avrei un altro aneddoto sulla copertura del test che vorrei condividere.

Abbiamo un grande progetto in cui, su Twitter, ho notato che, con 700 test unitari, abbiamo solo il 20% di copertura del codice .

Scott Hanselman rispose con parole di saggezza :

È GIUSTO il 20%? È il 20% che rappresenta il codice più colpito dai tuoi utenti? Puoi aggiungere altri 50 test e aggiungere solo il 2%.

Ancora una volta, risale al mio Testivus sulla risposta di copertura del codice . Quanto riso dovresti mettere nella pentola? Dipende.


Ovviamente deve esserci buon senso. Non è molto utile se il 50% del codice che stai testando sono commenti.
sanità mentale

2
È più nelle linee di ... la tua copertura è spesa per le funzionalità principali della tua applicazione o sta inutilmente testando funzionalità banali / simpatiche?
Jon Limjap,

sembra che una grande percentuale del codice sia rappresentata da boilerplate o gestione delle eccezioni o roba condizionale "modalità debug"
Erik Aronesty,

8

Per un sistema ben progettato, in cui i test unitari hanno guidato lo sviluppo dall'inizio, direi che l'85% è un numero piuttosto basso. Piccole classi progettate per essere testabili non dovrebbero essere difficili da coprire meglio di così.

È facile respingere questa domanda con qualcosa del tipo:

  • Le linee coperte non equivalgono alla logica testata e non si dovrebbe leggere troppo nella percentuale.

È vero, ma ci sono alcuni punti importanti da fare sulla copertura del codice. Nella mia esperienza questa metrica è in realtà abbastanza utile, se usata correttamente. Detto questo, non ho visto tutti i sistemi e sono sicuro che ce ne sono tonnellate in cui è difficile vedere l'analisi della copertura del codice che aggiunge un valore reale. Il codice può apparire così diverso e l'ambito del framework di test disponibile può variare.

Inoltre, il mio ragionamento riguarda principalmente cicli di feedback di test piuttosto brevi. Per il prodotto che sto sviluppando, il circuito di feedback più breve è abbastanza flessibile e copre tutto, dai test di classe alla segnalazione tra processi. Il test di un sottoprodotto consegnabile richiede in genere 5 minuti e per un ciclo di feedback così breve è infatti possibile utilizzare i risultati del test (e in particolare la metrica di copertura del codice che stiamo esaminando qui) per rifiutare o accettare commit nel repository.

Quando si utilizza la metrica di copertura del codice, non si deve semplicemente avere una percentuale fissa (arbitraria) che deve essere rispettata. A mio avviso, ciò non offre i reali vantaggi dell'analisi della copertura del codice. Definisci invece le seguenti metriche:

  • Low Water Mark (LWM), il numero più basso di linee scoperte mai visto nel sistema in prova
  • High Water Mark (HWM), la percentuale di copertura del codice più alta mai vista per il sistema in prova

Il nuovo codice può essere aggiunto solo se non andiamo al di sopra dell'LWM e non andiamo al di sotto dell'HWM. In altre parole, la copertura del codice non può diminuire e il nuovo codice dovrebbe essere coperto. Nota come dico che dovrei e non debba (spiegato di seguito).

Ma questo non significa che sarà impossibile ripulire la vecchia spazzatura ben collaudata per la quale non hai più bisogno? Sì, ed è per questo che devi essere pragmatico su queste cose. Ci sono situazioni in cui le regole devono essere violate, ma per la tua tipica integrazione quotidiana la mia esperienza è che queste metriche sono abbastanza utili. Danno le seguenti due implicazioni.

  • Il codice testabile è promosso. Quando aggiungi un nuovo codice devi davvero fare uno sforzo per renderlo testabile, perché dovrai provare a coprirlo con i tuoi casi di test. Il codice testabile è generalmente una buona cosa.

  • La copertura dei test per il codice legacy sta aumentando nel tempo. Quando si aggiunge un nuovo codice e non si riesce a coprirlo con un caso di prova, si può provare a coprire un po 'di codice legacy per aggirare la regola LWM. Questo imbarazzo a volte necessario almeno dà l'effetto collaterale positivo che la copertura del codice legacy aumenterà nel tempo, rendendo in pratica l'applicazione apparentemente rigorosa di queste regole.

E ancora, se il circuito di feedback è troppo lungo, potrebbe essere del tutto poco pratico impostare qualcosa di simile nel processo di integrazione.

Vorrei anche menzionare altri due vantaggi generali della metrica di copertura del codice.

  • L'analisi della copertura del codice fa parte dell'analisi dinamica del codice (al contrario di quella statica, ad esempio Lint). I problemi riscontrati durante l'analisi dinamica del codice (tramite strumenti come la famiglia purify, http://www-03.ibm.com/software/products/en/rational-purify-family ) sono cose come letture di memoria non inizializzate (UMR), perdite di memoria, ecc. Questi problemi possono essere trovati solo se il codice è coperto da un caso di test eseguito . Il codice che è il più difficile da coprire in un caso di test è di solito i casi anomali nel sistema, ma se si desidera che il sistema non riesca correttamente (ad es. Traccia di errore anziché arresto anomalo), è possibile che si desideri fare qualche sforzo per coprire i casi anomali anche nell'analisi dinamica del codice. Con solo un po 'di sfortuna, un UMR può portare a un segfault o peggio.

  • Le persone sono orgogliose di mantenere il 100% per il nuovo codice e discutono dei problemi di test con una passione simile a quella di altri problemi di implementazione. Come può essere scritta questa funzione in un modo più testabile? Come faresti per cercare di coprire questo caso anomalo, ecc.

E un aspetto negativo, per completezza.

  • In un grande progetto con molti sviluppatori coinvolti, tutti non saranno sicuramente un genio del test. Alcune persone tendono a utilizzare la metrica di copertura del codice come prova del fatto che il codice è stato testato e questo è molto lontano dalla verità , come menzionato in molte altre risposte a questa domanda. È UNICA metrica che può darti dei buoni benefici se usata correttamente, ma se viene usata in modo improprio può in effetti portare a test sbagliati. A parte i preziosi effetti collaterali sopra menzionati, una linea coperta mostra solo che il sistema in prova può raggiungere quella linea per alcuni dati di input e che può essere eseguito senza bloccarsi o bloccarsi.

7

Se questo fosse un mondo perfetto, il 100% del codice verrebbe coperto da test unitari. Tuttavia, poiché questo NON è un mondo perfetto, è una questione di ciò per cui hai tempo. Di conseguenza, raccomando di concentrarsi di meno su una percentuale specifica e di concentrarsi maggiormente sulle aree critiche. Se il tuo codice è ben scritto (o almeno un facsimile ragionevole), ci dovrebbero essere diversi punti chiave in cui le API sono esposte ad altro codice.

Concentrare le attività di test su queste API. Accertarsi che le API siano 1) ben documentate e 2) siano scritti casi di test corrispondenti alla documentazione. Se i risultati previsti non coincidono con i documenti, allora hai un bug nel tuo codice, documentazione o casi di test. Tutto ciò che è bene controllare.

In bocca al lupo!


6

Molti negozi non apprezzano i test, quindi se sei al di sopra dello zero c'è almeno qualche apprezzamento del valore - quindi probabilmente non zero non è male in quanto molti sono ancora zero.

Nel mondo .Net le persone spesso citano l'80% come ragionevole. Ma lo dicono a livello di soluzione. Preferisco misurare a livello di progetto: il 30% potrebbe andare bene per il progetto UI se hai Selenium, ecc. O test manuali, il 20% per il progetto del livello dati potrebbe andare bene, ma il 95% + potrebbe essere abbastanza realizzabile per l'azienda livello di regole, se non del tutto necessario. Quindi la copertura complessiva potrebbe essere, diciamo, del 60%, ma la logica aziendale critica potrebbe essere molto più elevata.

Ho anche sentito questo: aspira al 100% e raggiungerai l'80%; ma aspira all'80% e raggiungerai il 40%.

In conclusione: applica la regola 80:20 e lasciati guidare dal conteggio dei bug della tua app.



4

L'85% sarebbe un buon punto di partenza per i criteri di check-in.

Probabilmente avrei scelto una varietà di barre più alte per i criteri di spedizione, a seconda della criticità dei sottosistemi / componenti sottoposti a test.


54
Come sei arrivato a quella percentuale?
sanità mentale

Come nota a piè di pagina - questo può essere disordinato per i progetti in cui l'automazione è difficile - come sempre essere pragmatico su ciò che è realizzabile o desiderabile.
stephbu,

4
Principalmente attraverso la sperimentazione. È abbastanza facile ottenere una copertura del codice dell'80-90% per i test unitari relativi a Dev - andare più in alto richiede normalmente un intervento di test divino - o percorsi di codice davvero semplici.
Stephbu,

1
Comincio di solito con 1) principali percorsi di codice di runtime 2) evidenti casi di eccezione che lancio esplicitamente 3) casi condizionati che terminano con "fallimento" Questo ti porta di solito nell'intervallo 70-80 Quindi wackamole, bug e regressioni per casi angolari, parametro fuzzing ecc. Refactoring per consentire l'iniezione di metodi ecc. In genere concedo almeno tanto tempo per la scrittura / refactoring di test relativi agli sviluppatori come il codice principale stesso.
stephbu,

4

Uso cobertura e, qualunque sia la percentuale, consiglierei di mantenere aggiornati i valori dell'attività di cobertura-check. Come minimo, continua ad aumentare totallinerate e totalbranchrate appena al di sotto della tua attuale copertura, ma non abbassare mai quei valori. Collegare anche la proprietà Fail build ant a questa attività. Se la compilazione non riesce a causa della mancanza di copertura, conosci il codice aggiunto di qualcuno ma non lo hai testato. Esempio:

<cobertura-check linerate="0"
                 branchrate="0"
                 totallinerate="70"
                 totalbranchrate="90"
                 failureproperty="build.failed" />

4

Quando penso che il mio codice non sia sufficientemente testato dall'unità e non sono sicuro di cosa testare successivamente, utilizzo la copertura per aiutarmi a decidere cosa testare successivamente.

Se aumento la copertura in un test unitario, so che questo test unitario vale qualcosa.

Questo vale per il codice non coperto, coperto per il 50% o coperto per il 97%.


3
Non sono completamente d'accordo. Un test unitario vale qualcosa solo se c'è la possibilità che scoprirà un bug (o un bug che esiste ora o un bug di regressione in futuro); o se aiuta a documentare il comportamento della tua classe. Se un metodo è così semplice che non può davvero fallire, come un getter di una riga, allora c'è un valore zero nel fornire un test unitario per esso.
Dawood ibn Kareem,

6
Ho avuto dei bug in una riga getter. Dalla mia esperienza, non esiste un codice privo di bug. Non esiste un metodo che non può davvero fallire.
brickner,

1
Supponendo che il tuo getter a una riga sia utilizzato da altro codice che copri, e i test di quel codice passano, quindi hai anche indirettamente coperto il getter a una riga. Se non stai usando il getter, cosa sta facendo nel tuo codice? Sono d'accordo con David Wallace ... non è necessario testare direttamente le funzioni di supporto semplici che vengono utilizzate altrove se il codice e i test che dipendono dall'helper non mostrano che potrebbe esserci un problema.
Lowell Montgomery,

@LowellMontgomery e cosa succede se il test per l'altro codice non riesce a causa di quel getter a una riga (che non è stato testato)? Se ci fosse un test in atto per il one-liner, sarebbe molto più facile arrivare alla causa del fallimento. Diventa davvero brutto quando hai centinaia di liner non testati utilizzati in diversi luoghi.
Daniel,

Il presupposto era che i test avessero superato il getter a una riga. Se ha esito negativo (ad es. Dove si tenta di utilizzare il valore restituito del proprio getter di una riga), è possibile risolverlo. Ma a meno che non ci sia una ragione davvero pressante per essere così paranoici, devi tracciare la linea da qualche parte. La mia esperienza è stata che ho bisogno di dare la priorità a ciò che mi fa perdere tempo e attenzione e i "getter" (che funzionano) davvero semplici non hanno bisogno di test separati. Questo tempo può essere impiegato per rendere altri test migliori o una copertura più completa del codice che ha maggiori probabilità di fallire. (cioè sostengo la mia posizione originale, con David Wallace).
Lowell Montgomery,

4

Preferisco fare BDD, che utilizza una combinazione di test di accettazione automatizzati, possibilmente altri test di integrazione e test unitari. La domanda per me è quale dovrebbe essere la copertura target della suite di test automatizzati nel suo insieme.

A parte questo, la risposta dipende dalla metodologia, dalla lingua e dagli strumenti di test e copertura. Quando si fa TDD in Ruby o Python non è difficile mantenere una copertura del 100%, e vale la pena farlo. È molto più semplice gestire una copertura del 100% rispetto a una copertura del 90%. Cioè, è molto più facile colmare le lacune di copertura così come appaiono (e quando si fa bene TDD le lacune di copertura sono rare e di solito valgono il tuo tempo) piuttosto che gestire un elenco di lacune di copertura che non hai colto e perdere la copertura regressioni dovute al tuo costante background di codice scoperto.

La risposta dipende anche dalla storia del tuo progetto. Ho trovato quanto sopra utile solo nei progetti gestiti in questo modo dall'inizio. Ho notevolmente migliorato la copertura di grandi progetti legacy e ne è valsa la pena, ma non ho mai trovato pratico tornare indietro e colmare ogni vuoto di copertura, perché il vecchio codice non testato non è abbastanza ben compreso per farlo correttamente e velocemente.


3

Se hai fatto test di unità per un discreto periodo di tempo, non vedo alcun motivo per non avvicinarsi al 95% +. Tuttavia, come minimo, ho sempre lavorato con l'80%, anche quando non conoscevo i test.

Questo numero dovrebbe includere solo il codice scritto nel progetto (esclude framework, plugin, ecc.) E forse può anche escludere determinate classi composte interamente da codice scritto da chiamate a codice esterno. Questo tipo di chiamata dovrebbe essere deriso / stub.


3

In generale, dai vari documenti sulle migliori pratiche di eccellenza ingegneristica che ho letto, l'80% per il nuovo codice nei test unitari è il punto che offre il miglior rendimento. Andando oltre quel CC% si ottiene una quantità inferiore di difetti per la quantità di sforzo esercitato. Questa è una best practice utilizzata da molte grandi aziende.

Sfortunatamente, la maggior parte di questi risultati sono interni alle aziende, quindi non ci sono letterature pubbliche che posso indicarti.


3

La copertura del codice è eccezionale, ma solo fino a quando i benefici che ne derivano superano il costo / lo sforzo per raggiungerlo.

Abbiamo lavorato per un certo tempo a uno standard dell'80%, tuttavia abbiamo appena deciso di abbandonare questo processo e di concentrarci maggiormente sui nostri test. Concentrandosi sulla complessa logica aziendale ecc.,

Questa decisione è stata presa a causa della crescente quantità di tempo impiegata per inseguire la copertura del codice e mantenere i test unitari esistenti. Pensavamo di essere arrivati ​​al punto in cui il beneficio che stavamo ottenendo dalla nostra copertura del codice era considerato inferiore allo sforzo che dovevamo fare per raggiungerlo.


2

Risposta breve: 60-80%

Risposta lunga: penso che dipenda totalmente dalla natura del tuo progetto. In genere inizio un progetto testando ogni pezzo pratico. Al primo "rilascio" del progetto dovresti avere una percentuale di base abbastanza buona in base al tipo di programmazione che stai facendo. A quel punto puoi iniziare a "applicare" una copertura minima del codice.


2

Dai un'occhiata a Crap4j . È un approccio leggermente più sofisticato rispetto alla copertura del codice semplice. Combina misurazioni della copertura del codice con misurazioni della complessità e quindi mostra quale codice complesso non è attualmente testato.


2

La mia risposta a questo enigma è avere una copertura di linea del 100% del codice che puoi testare e una copertura di linea del 0% del codice che non puoi testare.

La mia pratica attuale in Python è quella di dividere i miei moduli .py in due cartelle: app1 / e app2 / e quando eseguo i test unitari calcola la copertura di quelle due cartelle e controlla visivamente ( un giorno devo automatizzare) che app1 abbia una copertura del 100% e app2 ha una copertura dello 0%.

Quando / se trovo che questi numeri differiscono dallo standard, indago e modifico il design del codice in modo che la copertura sia conforme allo standard.

Ciò significa che posso consigliare di ottenere una copertura del 100% del codice della libreria.

Di tanto in tanto rivedo app2 / per vedere se potevo testare qualsiasi codice lì, e se posso posso spostarlo in app1 /

Ora non sono troppo preoccupato per la copertura aggregata perché ciò può variare enormemente a seconda delle dimensioni del progetto, ma in genere ho visto dal 70% a oltre il 90%.

Con Python, dovrei essere in grado di escogitare un test del fumo in grado di eseguire automaticamente la mia app misurando la copertura e, auspicabilmente, ottenere un aggreagate del 100% quando si combina il test del fumo con cifre unittest.


2

Visualizzazione della copertura da un'altra prospettiva: un codice ben scritto con un chiaro flusso di controllo è il più facile da coprire, il più facile da leggere e di solito il codice meno difettoso. Scrivendo il codice con chiarezza e copribilità in mente e scrivendo i test unitari in parallelo con il codice, si ottengono i migliori risultati IMHO.


2

Secondo me, la risposta è "Dipende da quanto tempo hai". Cerco di raggiungere il 100% ma non faccio storie se non lo capisco con il tempo che ho.

Quando scrivo unit test, indosso un cappello diverso rispetto al cappello che indosso durante lo sviluppo del codice di produzione. Penso a ciò che il codice testato afferma di fare e quali sono le situazioni che possono romperlo.

Di solito seguo i seguenti criteri o regole:

  1. Che il test unitario dovrebbe essere una forma di documentazione su quale sia il comportamento previsto dei miei codici, ad es. l'output atteso ha dato un certo input e le eccezioni che i clienti potrebbero voler catturare (cosa dovrebbero sapere gli utenti del mio codice?)

  2. Che il test unitario mi avrebbe aiutato a scoprire cosa accadrebbe se non avessi ancora pensato. (Come rendere il mio codice stabile e robusto?)

Se queste due regole non producono una copertura del 100%, allora così sia. Ma una volta, ho il tempo, analizzo i blocchi e le linee scoperti e stabilisco se ci sono ancora casi di test senza unit test o se il codice deve essere sottoposto a refactoring per eliminare i codici non necessari.


1

Dipende molto dalla tua applicazione. Ad esempio, alcune applicazioni sono costituite principalmente da codice GUI che non può essere testato dall'unità.


5
Probabilmente dovresti usare Model View Presenter per la tua UI se ti trovi in ​​un ambiente TDD.
Charles Graham,

1

Non penso che ci possa essere una regola del genere in bianco e nero.
Il codice dovrebbe essere rivisto, con particolare attenzione ai dettagli critici.
Tuttavia, se non è stato testato, ha un bug!


Non voglio una regola, basta un feedback su qualsiasi esperienza personale sulla correlazione tra percentuale di copertura del codice ed efficacia del test unitario.
sanità mentale

1

A seconda della criticità del codice, ovunque dal 75% -85% è una buona regola empirica. Il codice di spedizione dovrebbe essere testato in modo più approfondito rispetto alle utility di casa, ecc.


1

Ciò deve dipendere dalla fase del ciclo di vita dello sviluppo dell'applicazione in cui ci si trova.

Se sei in fase di sviluppo da un po 'e disponi già di molto codice implementato e stai solo realizzando che devi pensare alla copertura del codice, devi controllare la tua copertura attuale (se esiste) e quindi utilizzare quella base per impostare le pietre miliari per ogni sprint (o un aumento medio nel corso di un periodo di sprint), il che significa assumersi il debito del codice pur continuando a fornire valore all'utente finale (almeno nella mia esperienza l'utente finale non si preoccupa un po 'se hai aumentato il test copertura se non vedono nuove funzionalità).

A seconda del tuo dominio non è irragionevole sparare per il 95%, ma dovrei dire in media che vedrai un caso medio dall'85% al ​​90%.


1

Penso che il miglior sintomo della corretta copertura del codice sia che la quantità di problemi concreti che i test unitari aiutano a risolvere è ragionevolmente corrispondente alla dimensione del codice unit test creato.


1

Penso che ciò che può importare di più sia sapere quale sia l'andamento della copertura nel tempo e capire le ragioni dei cambiamenti nell'andamento. Se consideri i cambiamenti nella tendenza come buoni o cattivi dipenderà dalla tua analisi del motivo.


0

Avevamo come target> 80% fino a qualche giorno fa, ma dopo aver utilizzato molto codice generato, non ci interessa la percentuale di età, ma piuttosto facciamo in modo che il revisore faccia una chiamata sulla copertura richiesta.


0

Dal post di Testivus penso che il contesto di risposta dovrebbe essere il secondo programmatore. Detto questo da un punto di vista pratico, abbiamo bisogno di parametri / obiettivi per cui lottare. Ritengo che questo possa essere "testato" in un processo Agile analizzando il codice che abbiamo l'architettura, la funzionalità (user story), e poi ne viene fuori un numero. In base alla mia esperienza nell'area delle telecomunicazioni, direi che il 60% è un buon valore da verificare.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.