Risposte alle tue domande
C'è qualcosa come avere troppi test unitari?
Certo ... Potresti, ad esempio, avere più test che sembrano essere diversi a prima vista ma testare davvero la stessa cosa (logicamente dipendono dalle stesse linee di "interessante" codice dell'applicazione sotto test).
Oppure potresti testare gli interni del tuo codice che non emergono mai verso l'esterno (ovvero, non fanno parte di alcun tipo di contratto di interfaccia), dove si potrebbe discutere se ciò abbia un senso, a tutti. Ad esempio la formulazione esatta dei messaggi di registro interni o altro.
Mi è stato assegnato il compito di scrivere unit test per un'applicazione esistente. Dopo aver finito il mio primo file, ho 717 righe di codice di prova per 419 righe di codice originale.
Questo mi sembra abbastanza normale. I test impiegano molte righe di codice per l'installazione e lo smontaggio oltre ai test effettivi. Il rapporto può migliorare o no. Io stesso sono abbastanza pesante, e spesso investo più tempo e tempo sui test rispetto al codice reale.
Questo rapporto diventerà ingestibile man mano che aumentiamo la copertura del nostro codice?
Il rapporto non tiene conto di così tanto. Esistono altre qualità di test che tendono a renderle ingestibili. Se devi regolarmente refactoring di un sacco di test quando esegui modifiche piuttosto semplici nel tuo codice, dovresti dare una buona occhiata ai motivi. E quelli non sono quante linee hai, ma come ti avvicini alla codifica dei test.
La mia comprensione del test unitario era di testare ogni metodo della classe per garantire che ogni metodo funzionasse come previsto.
Ciò è corretto per i test "unitari" in senso stretto. Qui, "unità" è qualcosa come un metodo o una classe. Il punto del test "unit" è testare solo una specifica unità di codice, non l'intero sistema. Idealmente, dovresti rimuovere tutto il resto del sistema (usando double o quant'altro).
Tuttavia, nella richiesta pull il mio responsabile tecnico ha notato che avrei dovuto concentrarmi su test di livello superiore.
Quindi sei caduto nella trappola dell'ipotesi che le persone intendessero effettivamente test unitari quando dicevano test unitari. Ho incontrato molti programmatori che dicono "unit test" ma significano qualcosa di completamente diverso.
Ha suggerito di testare 4-5 casi d'uso che sono più comunemente usati con la classe in questione, piuttosto che testare esaurientemente ciascuna funzione.
Certo, concentrarsi solo sull'80% dei codici importanti riduce anche il carico ... Apprezzo il fatto che tu pensi molto al tuo capo, ma questo non mi sembra la scelta ottimale.
Per me, la copertura del test unitario al 100% è un obiettivo elevato, ma anche se avessimo raggiunto solo il 50%, sapremmo che il 100% di quel 50% era coperto.
Non so cosa sia la "copertura unit test". Suppongo che intendi "copertura del codice", ovvero che dopo aver eseguito la suite di test, ogni riga di codice (= 100%) è stata eseguita almeno una volta.
Questa è una buona metrica del campo da baseball, ma di gran lunga non è il migliore standard per cui si possa puntare. L'esecuzione delle righe di codice non è il quadro completo; questo non tiene conto di percorsi diversi attraverso rami complicati e nidificati, per esempio. È più una metrica che punta il dito su pezzi di codice che sono testati troppo poco (ovviamente, se una classe ha una copertura del codice del 10% o del 5%, allora qualcosa non va); d'altra parte una copertura del 100% non ti dirà se hai effettuato test sufficienti o se hai eseguito correttamente i test.
Test d'integrazione
Mi irrita sostanzialmente quando le persone parlano costantemente di unit test oggi, per impostazione predefinita. Secondo me (ed esperienza), il test unitario è ottimo per le librerie / API; in più aree orientate al business (di cui parliamo di casi d'uso come nella domanda in corso), non sono necessariamente l'opzione migliore.
Per il codice generale dell'applicazione e nel business medio (dove guadagnare denaro, rispettare scadenze e soddisfare la soddisfazione del cliente è importante e si desidera principalmente evitare bug che sono direttamente in faccia all'utente o che potrebbero portare a disastri reali - non lo siamo parlando del lancio di missili della NASA qui), l'integrazione o i test di funzionalità sono molto più utili.
Quelli vanno di pari passo con lo sviluppo guidato dal comportamento o lo sviluppo guidato dalle caratteristiche; quelli non funzionano con (severi) test unitari, per definizione.
Per farla breve (ish), un test di integrazione / funzionalità esercita l'intero stack dell'applicazione. In un'applicazione basata sul web, si comporterebbe come un browser che fa clic sull'applicazione (e no, ovviamente non deve essere così semplicistico, ci sono framework molto potenti là fuori per farlo - controlla http: // cucumber. io per un esempio).
Oh, per rispondere alle tue ultime domande: fai in modo che tutto il tuo team abbia un'elevata copertura dei test assicurandoti che una nuova funzione sia programmata solo dopo che il suo test è stato implementato e fallito. E sì, questo significa ogni caratteristica. Questo ti garantisce una copertura delle funzioni al 100% (positiva). Per definizione garantisce che una funzione dell'applicazione non "andrà mai via". Non garantisce una copertura del codice del 100% (ad esempio, a meno che non si programmino attivamente funzioni negative, non si eserciterà la gestione degli errori / gestione delle eccezioni).
Non ti garantisce un'applicazione senza bug; ovviamente vorrai scrivere test di funzionalità per situazioni buggy ovvie o molto pericolose, input dell'utente errato, hacking (ad esempio, gestione della sessione circostante, sicurezza e simili) ecc .; ma anche solo programmare i test positivi ha un enorme vantaggio ed è abbastanza fattibile con quadri moderni e potenti.
I test di funzionalità / integrazione ovviamente hanno una loro lattina di worm (ad esempio, prestazioni; test ridondanti di framework di terze parti; poiché di solito non usi i doppi, tendono anche a essere più difficili da scrivere, nella mia esperienza ...), ma io ' d prendere un'applicazione testata con funzionalità positive al 100% su un'applicazione testata con copertura del codice al 100% (non libreria!) ogni giorno.