Ogni test unitario dovrebbe poter essere eseguito indipendentemente da altri test?


24

Supponi di avere dei test per due metodi di una classe. Il primo metodo raccoglie i dati da un altro livello e li inserisce in una sorta di memoria indipendente dal runtime (come una tabella SQL), quindi tutti i dati gestiti da questo test sono codificati nel test. Il secondo metodo è responsabile di prendere i dati da dove il primo metodo li ha lasciati e trasformarli in qualche modo (calcolo, spostare alcune parti altrove, ecc.).

Ora questo secondo metodo potrebbe avere input hardcoded come il primo, oppure si potrebbe presumere che i due test sarebbero stati eseguiti in sequenza e potrebbe riprendere da dove si era interrotto il primo test, prendendo i dati che erano realmente memorizzati dal primo test.

Se avessi scelto la seconda opzione, avresti davvero una buona idea che i due metodi funzionassero bene insieme, tuttavia, se il 1 ° test fallisse, tutti i test successivi fallirebbero, eliminando i vantaggi del test aiutando a isolare i bug più rapidamente.

Se avessi scelto la prima opzione, ogni metodo sarebbe stato isolato e testato indipendentemente, ma non avresti mai saputo che potevano davvero funzionare insieme correttamente.

Qual è l'opzione migliore qui? Esiste una sorta di alternativa come avere un singolo test per ogni metodo isolato con hardcoding e quindi test più grandi che contengono entrambi i metodi in uno?


2
In realtà vorrei poter facilmente randomizzare l'ordine dei test unitari ogni volta che vengono eseguiti. In questo momento corrono in un ordine sconosciuto, sebbene relativamente fisso.
Giobbe

Risposte:


11

Se avessi scelto la prima opzione, ogni metodo sarebbe stato isolato e testato indipendentemente, ma non avresti mai saputo che potevano davvero funzionare insieme correttamente.

Se i tuoi metodi sono veramente indipendenti, questo non dovrebbe importare. Il tuo secondo metodo dovrebbe:

a) Funziona correttamente se presentato con dati validi.

b) Fallimento sensato e coerente quando presentato con dati non validi.

Allo stesso modo il tuo primo metodo dovrebbe fare lo stesso. Quindi, finché gestisci i casi di errore, funzioneranno insieme correttamente.

Se si desidera verificare che i metodi funzionino correttamente insieme, si tratta di test di integrazione, non di test unitari.


27

Se i test non possono essere eseguiti in modo indipendente, non sono test unitari.

Un test unitario non deve fare affidamento su alcuno stato esterno, ad esempio il contenuto di una tabella del database. Dovrebbe testare puramente un'unità di codice in isolamento.

I test che alterano o richiedono un determinato stato sono validi, possono ad esempio far parte dei test di integrazione e in tali casi è importante assicurarsi che venga eseguita un'installazione appropriata, ma questi non sarebbero test unitari. In questo caso, non consiglierei ancora che un test ne richieda un altro. In questo caso, probabilmente dovresti scomporre il codice richiesto in un metodo di configurazione separato. Potresti avere un test che chiama semplicemente il codice di configurazione e verifica che non venga generata alcuna eccezione, ad esempio, e quindi un altro test che utilizza in modo attivo la configurazione dei dati nel metodo di configurazione.


@Steve, quindi in questo esempio diresti: un test per il metodo 1, un test per il metodo 2 e un test che esegue 1 e 2 nello stesso test?
Morgan Herlocker,

2
Sì. i primi due sarebbero test unitari, il terzo suona come un test di integrazione.
Steve

se hai un modulo cliente e un modulo ordini e l'ordine non può essere creato senza relazione con il cliente. Come lo testerai indipendentemente dal modulo cliente: crea un record cliente nel database con sql (inserisci nel cliente) o usa Customer.createCustomer (). E IMHO usa il secondo è meglio, poiché non è necessario impelementare alcuna logica nei test, ma funziona solo se il test sulla creazione dei clienti passa.
Dainius,

@Dainius. In uno scenario di test unitario, in genere si utilizzano oggetti fittizi, quindi si passa un cliente fittizio al modulo dell'ordine. Hai ragione nel non voler usare sql in questo caso.
Steve

sembra che in ogni scenario in cui il metodo B dipende dal metodo A, ci sarà quasi sempre un metodo C che chiama A quindi chiama B. Dato che in questo caso, è possibile testare A, B e C in modo indipendente.
Morgan Herlocker,

9

Sono sicuro che al momento sembra giusto avere un test unitario B che dipende dallo stato lasciato dal test unitario B. Ma considera tra un anno, quando avrai mille test unitari. Vuoi davvero aspettare dieci minuti per completare l'intera suite di test ogni volta che devi apportare una modifica?

Dipende ovviamente dal tuo stile di sviluppo, ma se desideri sperare in uno sviluppo decente guidato dai test, in cui potresti eseguire un singolo test molte volte durante lo sviluppo di una funzionalità, ti suggerisco di dare a ciascun test la capacità di stare da solo.


1
+1 Raskolnikov, non ho considerato il fatto che questo sarebbe un grande spreco di tempo in seguito quando avrò "eseguito tutti i test" in seguito.
Morgan Herlocker,

3

Sembra che tu stia parlando della configurazione del test, che può essere eseguita in diversi modi. Volete una copia pulita dei dati del test (chiamato apparecchio) per ogni test, quindi ognuno di essi non dovrebbe dipendere l'uno dall'altro.

Esistono diversi framework che consentono questo tipo di test e strumenti come DBUnit che consentono di creare e demolire rapidamente strutture di dati all'inizio e alla fine dei test e delle suite di test.

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.