2009-09-03 13 views
28

Nella verifica dell'unità, il metodo di configurazione viene utilizzato per creare gli oggetti necessari per il test.Test delle unità: è una buona pratica avere asserzioni nei metodi di configurazione?

In questi metodi di installazione, mi piace usare le asserzioni: so quali valori voglio vedere in quegli oggetti e mi piace documentare tale conoscenza tramite un'asserzione.

In un recente post su unit tests calling other unit tests qui su StackOverflow, la sensazione generale sembra essere che i test di unità dovrebbe non chiamate altri test: La risposta a questa domanda sembra essere che si dovrebbe refactoring la configurazione, in modo che i casi di test non dipendono l'uno dall'altro.

Ma non c'è molta differenza in un "setup-with-asserts" e un test di unità che chiama altri test di unità.

Quindi la mia domanda: è una buona pratica avere asserzioni nei metodi di configurazione?

EDIT:

La risposta si rivela essere: questa non è una buona pratica in generale. Se è necessario testare i risultati del setup, si consiglia di aggiungere un metodo di test separato con le asserzioni (la risposta che ho spuntato); per documentare l'intenzione, prendere in considerazione l'utilizzo di asserzioni Java.

+1

Leggi questo articolo su come scrivere buoni test unitari: http://blog.codeville.net/2009/08/24/writing-great-unit-tests-best-and-worst-practises/ – Kane

+0

+1 per la domanda intelligente – KLE

risposta

14

Invece di asserzioni nel setup per verificare il risultato, ho usato un semplice test (un metodo di test lungo le altre, ma posizionato come primo metodo di test).

ho visto diversi vantaggi:

  • Il setup mantiene breve e focalizzato, per migliorare la leggibilità.
  • Le asserzioni vengono eseguite una sola volta, che è più efficiente.

Uso e discussione:

Per esempio, io chiamo il metodo testSetup().

Per utilizzarlo, quando ho alcuni errori di test in quella classe, so che se testSetup() ha un errore, non ho bisogno di preoccuparmi degli altri errori, ho bisogno di aggiustarlo prima.

Se qualcuno è infastidito da questo e vuole rendere esplicita questa dipendenza, il metodo test() può essere chiamato testSetup(). Ma non penso che importi. Il mio punto è che, in JUnit, si può già avere qualcosa di simile nel resto del vostro test:

  1. alcuni test che mettono alla prova il codice locale,
  2. e alcuni test che è chiamate codice più globale, che indirettamente chiamate lo stesso codice del test precedente.

Quando si legge il risultato del test in cui entrambi fallire, si dispone già di prendersi cura di questa dipendenza che non è nella prova, ma nel codice essere chiamato. Devi prima sistemare il test semplice e poi rieseguire il test globale per vedere se fallisce ancora. Questo è il motivo per cui non sono infastidito dalla dipendenza implicita che ho spiegato prima.

+2

Questa mattina ho discusso la questione con un collega, e abbiamo trovato anche questa soluzione. Buono a sapere che hai un'esperienza positiva con esso! – avandeursen

+0

@Kaka Grazie per il tuo cortese commento e per il rinforzo fornito dal tuo feedback. :-) – KLE

+0

@KLE: questa è una strategia interessante ed efficiente. Ma mi chiedo come si assicuri che 'testSetup()' venga eseguito quando si esegue il test con un filtro (ad esempio '--gtest_filter'). – Sampath

9

Sono diversi scenari; Non vedo la somiglianza.

I metodi di installazione devono contenere il codice comune a (idealmente) tutti i test in un dispositivo. Di conseguenza, non c'è nulla di intrinsecamente sbagliato nell'inserire gli asserti in un metodo di configurazione di prova se certe cose devono essere vere prima che il resto del codice di test venga eseguito. La configurazione è un'estensione del test; fa parte del test nel suo complesso. Se l'asserzione viaggia, le persone scopriranno quale prerequisito è fallito.

D'altra parte, se l'installazione è abbastanza complicata da far ritenere che la necessità di affermarlo sia corretta, potrebbe essere un segnale di avvertimento. Inoltre, se tutti i test non richiedono l'output completo dell'impostazione, significa che l'apparecchiatura ha una scarsa coesione e deve essere suddivisa in base a scenari e/o refactored.

In parte è per questo che tendo a non utilizzare i metodi di installazione. Ove possibile, utilizzo metodi di produzione privati ​​o simili per impostare le cose. Rende il test più leggibile ed evita confusione. A volte questo non è pratico (ad esempio lavorando con classi strettamente accoppiate e/o quando si scrivono test di integrazione), ma per la maggior parte dei miei test fa il lavoro.

9

Avere le asserzioni nei metodi Setup/TearDown non è consigliabile. Rende il test meno leggibile se l'utente deve "capire" che parte della logica di test non è nel metodo di test. Ci sono momenti in cui non si ha scelta ma usare i metodi di setup/teardown per qualcosa di diverso da quello per cui erano destinati.

C'è un problema più grande in questa domanda: un test che chiama un altro test, è un odore per qualche problema nei test. Ogni test dovrebbe testare un aspetto specifico del tuo codice e dovrebbe avere solo una o due asserzioni, quindi se il test chiama un altro test potresti testare troppe cose in quel test. Per ulteriori informazioni leggere: Unit Testing: One Test, One Assertion - Why It Works

+0

Puntatore interessante per un test/una asserzione, e mi piace la tua riformulazione in "uno o due". – avandeursen

+1

L'URL è rotto. Ecco uno aggiornato. [Unit Testing: One Test, One Assertion - Why It Works] (http://blog.astrumfutura.com/2009/02/unit-testing-one-test-one-assertion-why-it-works/) – James

3

Seguire le decisioni del cuore/battito di ciglia. Asserisce all'interno di un metodo di installazione in grado di documentare l'intento; miglioramento della leggibilità.Quindi personalmente ti sosterrò su questo.
È diverso da un test che chiama altri test, il che è negativo. Nessun isolamento del test. Un test non dovrebbe influenzare l'esito di un altro test.

Anche se non si tratta di un caso d'uso freq, a volte uso Assert all'interno di un metodo di installazione in modo che possa sapere se l'impostazione del test non è avvenuta come intendevo; di solito quando ho a che fare con componenti che non ho scritto io stesso. Un errore di asserzione che dice 'Setup fallito!' nella scheda degli errori - mi aiuta rapidamente a intervenire sul codice di configurazione invece di dover esaminare un gruppo di test non riusciti.

Un errore di installazione di solito dovrebbe causare il fallimento di tutti i test in quell'attrezzatura - che è un odore che il naso dovrebbe presto raccogliere. "Tutti i test falliti di solito implicano il fallimento dell'installazione" Quindi le asserzioni non sono sempre necessarie. Detto ciò è pragmatico, guarda il tuo contesto specifico e "Aggiungi ai gusti".

+0

Buono punti - Grazie. Ciò significa che l'uso di JUnit asserisce per due scopi diversi: (1) intento del documento; (2) Verificare che i risultati siano come attesi. – avandeursen

3

Uso gli asseriti Java, piuttosto che quelli JUnit, nei casi in cui è necessario qualcosa di simile. per esempio. quando si utilizza qualche altra classe di utilità per impostare i dati di test .:

byte[] pkt = pktFactory.makePacket(TIME, 12, "23, F2"); 
assert pkt.length == 15; 

In mancanza ha l'implicazione 'sistema non è in uno stato ancora per cercare per eseguire questo test'.

+0

Mi piace l'idea. Ciò solleva la questione generale se sia una buona pratica combinare i metodi Java assert e JUnit Assert, ma mi piace il tuo ragionamento. – avandeursen

Problemi correlati