C'è qualche valore nella scrittura di unit test per il codice che funziona già quando si ereditano le applicazioni?


27

Ovviamente alcune vecchie applicazioni non possono essere o è estremamente difficile testare l'unità a causa del modo in cui è stato scritto in primo luogo.

Ma in alcuni punti, come alcuni metodi di supporto che potrebbero essere probabilmente testati in unità, dovrei preoccuparmi di scrivere test unitari per loro?

Voglio dire, potrebbero essere scritti come un cane, ma per quanto complessamente fragile la logica, la prova del tempo ha dimostrato che funziona come dovrebbe. Dovrei preoccuparmi del test unitario solo se sto dicendo di riprovare il fattore o devo scrivere test unitari per loro ogni volta che ho tempo?

C'è qualche valore nel fare questo?

Tieni anche conto del fatto che la definizione del metodo può essere vaga e che potrebbe essere necessario ricercare ciò che alcuni metodi dovrebbero effettivamente fare in determinate condizioni.


4
Fatti un favore e leggi Lavorare in modo efficace con il codice legacy . Se è un intero libro dedicato a rispondere a questa e ad altre domande correlate.
Rein Henrichs,

Risposte:


15

Penso che dovresti sicuramente scrivere quanti più test possibili per l'applicazione. Ti aiuteranno a imparare la base di codice e prepararti per l'eventuale refactoring o nuovo sviluppo.

Esistono alcuni tipi di test che puoi scrivere in quello scenario, ognuno ha i suoi meriti. Scrivere questi test ti insegnerà molto sull'applicazione con cui hai a che fare.

Prima di tutto, prima di iniziare a scrivere test per correttezza, scrivi test che catturino il comportamento attuale , giusto o sbagliato. È una scommessa abbastanza sicura che scoprirai bug in casi angolari o in parti del codice che non sono stati testati a fondo eseguendo il programma. Non preoccuparti di cosa dovrebbe fare il codice, basta catturare ciò che fa. Man mano che procedi, non preoccuparti di leggere il codice o di dedicare molto tempo a capire quale dovrebbe essere l'output. Basta eseguire il test e acquisire l'output in un'asserzione.

Ciò ti fornirà una solida base per capire come funziona il codice e dove possono essere i principali punti di dolore o aree deboli. Se scopri i bug, puoi avvicinare le persone con il potere di decidere se valgono la pena correggerli e prendere quelle decisioni.

Successivamente, è possibile scrivere alcuni test più grandi (nell'ambito) che coprono parti del codice che potrebbero non essere facilmente testabili dall'unità ma in cui sarebbe comunque importante testare il più possibile i flussi di lavoro. Questi test del flusso di lavoro o test di integrazione , a seconda di come li desideri, ti forniranno una buona base per il refactoring di tali flussi di lavoro per renderli più testabili e proteggerti quando è necessario aggiungere una nuova funzionalità che potrebbe influire su un flusso di lavoro esistente.

Nel tempo, creerai una suite di test che è lì per aiutare te o la persona successiva che finisce per ereditare l'applicazione.


13

Vedo i test unitari come specifiche, non semplici test. Nel caso specifico che hai menzionato, il valore reale verrà quando hai un test unitario in atto prima di apportare qualsiasi modifica per conformarti alle nuove specifiche. Se hai intenzione di cambiare il codice ereditato, il modo migliore che vedo è di avere test unitari per la funzionalità, questo non solo porterà una rete di sicurezza, ma ci aiuterà anche a portare più chiarezza su ciò che fa quella particolare unità. Potrebbe anche costringerti a fare alcune ricerche, come menzionato da te, che è buono per la comprensione. Quindi la mia idea è quella di mettere in atto un test unitario di un modulo prima che stia per subire una modifica.


Scrivi i test nella lingua di livello più alto che funzionerà. Quando viene richiesto di stimare il tempo necessario per apportare una modifica, includere il tempo necessario per scrivere i test mancanti. Potresti impiegare più tempo per apportare la modifica, ma inserirai molti meno bug nel campo.
Kevin Cline,

8
 > Is there any value in writing unit tests for code that 
 > already works when inheriting applications?

NO . Dalla mia esperienza, esiste una cattiva relazione costi / benefici per la scrittura di unit test dopo che il codice di produzione è stato scritto perché è abbastanza improbabile / difficile trovare modi per testare il codice in isolamento senza un pesante refactoring. Uno dei vantaggi dello sviluppo guidato dai test è che si ottiene un codice liberamente accoppiato. Se in seguito si scrivono i test, è molto probabile che il codice sia strettamente accoppiato.

SÌ, è possibile scrivere test di integrazione per l'applicazione per quelle funzioni in cui si prevede di apportare modifiche. In questo modo puoi fare un test di regressione per vedere se le tue modifiche rompono qualcosa.

dal punto di vista della qualità e degli sviluppatori, è utile avere dei test.

NO dal punto di vista commerciale perché è molto difficile vendere al cliente che è necessario tempo / denaro per non ottenere un valore commerciale reale, ma la vaga promessa che i cambiamenti del business non peggioreranno le cose.


+1 per i test di integrazione anziché il test unitario per questo caso. Consiglio molto pragmatico
gbjbaanb

5

Se possibile, c'è ancora più motivo per scrivere test per il codice esistente che "funziona già". Se non ci sono test, allora è probabile che il codice sia maturo con gli odori e che potrebbe essere utilizzato un ampio refactoring per migliorare; la suite di test ti aiuterà a refactoring. Potrebbe anche rivelare che il codice originale non funziona correttamente; Ricordo una volta che ho scritto un test per un metodo per generare un rapporto sulle vendite e ho scoperto che non stava calcolando le cose correttamente, quindi le vendite sono state qualche migliaio di dollari in più di quanto non fossero in realtà, e nessuno sapeva da cinque anni che il codice era in produzione (per fortuna non è stata la vera fine finanziaria delle cose, solo una stima del rapporto sulle vendite).

Ovviamente, questo consiglio si applica solo se in realtà è possibile scrivere i test. Nella mia esperienza, una base di codice senza test è quasi impossibile per il retrofit dei test perché dovresti riscrivere metà dei moduli di codice per essere abbastanza astratta da supportare prima i test, e non sarai in grado di farlo.


Perché un downvote per affermare la verità?
Wayne Molina,

4

Assolutamente sì , perché i test unitari non devono verificare la correttezza ma caratterizzare il comportamento effettivo del sistema. Soprattutto con un progetto legacy, molti dei requisiti sono implicitamente codificati nel comportamento reale.

Questa caratterizzazione serve come base di funzionalità. Anche se il comportamento non è corretto dal punto di vista aziendale, si impedisce che il comportamento peggiori ulteriormente. Ottenere la trazione in un progetto legacy può essere difficile, e questo ti dà una base di partenza in modo da poter andare avanti senza peggiorare le cose.

Quindi, scrivi tutti i test unitari che puoi. Per il codice che non può essere testato, riformattare il codice in modo da separare le dipendenze introducendo "cuciture" nel codice, posizioni in cui è possibile separare il codice che si desidera verificare dal codice che non si desidera verificare.

Le idee di unit test come test di caratterizzazione e cuciture sono i punti principali di Working Effectively with Legacy Code di Michael Feathers, un libro che consiglio vivamente.


2

Ho riflettuto su questo io stesso, dato che nel nostro sistema ci sono parecchi scritti privi di documenti scritti in modo sgradevole, ma che funzionano nel nostro sistema.

Fai un bel punto:

Dovrei preoccuparmi del test unitario solo se sto dicendo di riprovare il fattore o devo scrivere test unitari per loro ogni volta che ho tempo?

Se i requisiti cambiano, penso che sarebbe molto utile scrivere i test delle unità. Altrimenti non mi preoccuperei soprattutto perché non saresti in grado di scrivere test adeguati, perché non conosci tutte le condizioni.

ogni volta che ho tempo?

Hai tempo quando viene data la priorità, giusto ?, quindi non accadrà mai comunque. :)


1

Stai cercando di sfruttare aspetti di quella base di codice che non sono stati precedentemente utilizzati in un'applicazione di produzione? Scrivi prima i test unitari per quegli scenari. Devi essere in grado di dare la priorità al tuo lavoro qui, e penso che The Art of Unit Testing abbia avuto qualche consiglio in proposito (in particolare come affrontare i test di basi di codice legacy).


1

Non dare per scontato che tutto funzioni solo perché l'applicazione è attiva e in esecuzione ... in genere, il "test del tempo" mostra solo che a) non hai ancora trovato il resto dei difetti oppure b) le persone che hanno trovato non li hanno segnalati. (O forse entrambi.) E anche il codice che presumibilmente funziona ora potrebbe non funzionare la prossima volta che devi apportare una modifica.

I test unitari forniscono una misura della certezza che determinate funzionalità rimangono intatte, fornendo al contempo un modo per dimostrarlo per un numero ragionevole di casi. Questo è significativamente più prezioso di "curiosare e testare questo", anche per una singola correzione di bug. (Frugare è più simile all'equivalente dell'integrazione o dei test di sistema, quindi in questo senso testare manualmente l'app può coprire più di quanto i test unitari possano fare da soli, ma è comunque tempo trascorso in modo inefficiente. Anche un metodo per automatizzare quei test è meglio che farli manualmente.)

Dovresti assolutamente scrivere dei test quando cambi codice, sia che si tratti di riparazioni o refactoring. Potresti fare bene a scrivere test come puoi, se non altro per risparmiare un po 'di tempo la prossima volta che devi correggere un difetto (e ci sarà una prossima volta) ... anche se in questo caso, dovrai deve bilanciare quel tempo con le aspettative delle persone che fingono che il software sia sempre privo di difetti e che quindi il tempo speso per la futura manutenzione sia "sprecato". (Ciò non significa che dovresti ignorare le pianificazioni attuali, però.) Ad un certo punto, se lo fai, avrai una copertura sufficiente da poter iniziare a dimostrare il valore del test su applicazioni legacy e che potrebbe aiutarti a spendere quel tempo su app future, che alla fine dovrebbero liberare tempo da dedicare allo sviluppo produttivo.


0

Dal mio cuore di terra lala, dirò di sì e non solo, ma lo hackererò, lo rifatteremo e continuerò i test, ma assicurerò di non restare indietro in altri importanti progetti. Come programmatore di lavoro, se il tuo lavoro è a rischio o se un manager ti ha detto di assumere la proprietà, allora sì. Se il team o l'azienda potrebbero soffrire, negoziare con il proprio manager per fargli sapere che è necessario eseguire i test per evitare che la società si verifichi. Se dice di non preoccuparti, allora sei fuori di testa (non necessariamente, la delega della colpa è un'abilità di gestione, quindi assicurati di essere fuori di testa ... davvero!)

In bocca al lupo!

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.