Il test dell'unità non interrompe il principio DRY?

11

Ogni volta che scrivo test unitari ho sempre cercato di avere un singolo assert per test per rendere più facile il debugging quando i test falliscono. Tuttavia, seguendo questa regola, mi sento come se stessi copiando costantemente lo stesso codice in ogni test e avendo più test diventa più difficile tornare a leggere e mantenere.

Quindi i test di asserzione singola violano DRY?

E C'è una buona regola da seguire per trovare un buon equilibrio, come se avessi un test per metodo ? *

* Mi rendo conto che probabilmente non esiste una soluzione valida per tutti, ma c'è un modo consigliato per avvicinarsi a questo?

    
posta Korey Hinton 26.08.2013 - 22:18
fonte

3 risposte

14

I test di unità appropriate hanno una convenzione di denominazione che aiuta identifica immediatamente ciò che ha fallito:

public void AddNewCustomer_CustomerExists_ThrowsException()

Ecco perché hai un'asserzione per test, in modo che ogni metodo (e il suo nome) corrisponda alla condizione che stai affermando.

Come hai giustamente sottolineato, ogni nuovo test avrà un codice di configurazione simile. Come con qualsiasi codice, puoi rifattorizzare il codice comune nel proprio metodo per ridurre o eliminare la duplicazione e rendere il tuo codice più ASCIUTTO. Alcuni framework di testing sono progettati specificamente per consentire a di inserire il codice di installazione in un unico punto .

In TDD, nessun test è YAGNI, perché scrivi test basati solo su ciò che richiedi al tuo codice. Se non ne hai bisogno, non scriverà il test.

    
risposta data 26.08.2013 - 22:28
fonte
5

So does single-assertion testing violate DRY?

No, ma promuove la violazione.

Detto questo, il buon design orientato agli oggetti tende a uscire dalla finestra per i test unitari, soprattutto per una buona ragione. È più importante che i test unitari siano isolati l'uno dall'altro in modo che il test possa essere interrogato in modo isolato e, se necessario, risolto con la certezza che non si rompono altri test. Fondamentalmente la correttezza e leggibilità del test è più importante delle sue dimensioni o manutenibilità.

Francamente, non sono mai stato un fan di quello che asserisco per regola di test per i motivi che descrivi: porta a un sacco di codice standard difficile da leggere, facile da falsare e difficile da risolvere bene se si refactoring (che ti spinge a refactoring di meno).

Se si suppone che una funzione restituisca un elenco di "foo" e "bar" per un dato input, ma in qualsiasi ordine è perfettamente corretto usare due asserzioni per verificare che entrambi siano nel set di risultati. Dove ti trovi nei guai è quando un singolo test sta controllando due input o due effetti collaterali e non sai quale dei due ha causato l'errore.

Lo vedo come una variazione del Principio di Responsabilità Unica: dovrebbe esserci solo una cosa che può far fallire un test, e in un mondo ideale che il cambiamento dovrebbe interrompere solo un test.

Ma alla fine è un compromesso. È più probabile che tu spenda più tempo a mantenere tutto il codice di copia incolla, o passerai più tempo a cercare le cause principali quando i test potrebbero essere interrotti da più fonti. Finché scrivi - alcuni test, probabilmente non importa troppo. Nonostante il mio disprezzo per i test monodimensionali, tendo a sbagliare sul lato di altri test. Il tuo chilometraggio può variare.

    
risposta data 26.08.2013 - 22:42
fonte
2

No. Questo sembra essere il modo in cui lo stai facendo. A meno che tu non abbia trovato un riferimento notevole dove sostengono che questa è una buona pratica.

Utilizza un dispositivo di test (anche se nella terminologia XUnit l'insieme di test, l'installazione e l'eliminazione sono l'apparecchiatura) , cioè alcuni set o esempi che si applicano a tutti i tuoi test.

Usa metodi come faresti normalmente per strutturare il tuo codice. Al momento del refactoring, non si applica il solito TDD Red-Green-Refactor , invece applicare "Refactoring in the Red". Cioè,

  1. interrompe deliberatamente il test,
  2. fai il tuo refactoring
  3. correggi il tuo test

In questo modo sai che i test danno ancora risultati positivi e negativi.

Esistono diversi formati standard per i test. Ad esempio, Disponi, agisci, asserisci o Dato When, Then (BDD) . Prendi in considerazione l'utilizzo di una funzione separata per ogni passaggio. Dovresti essere in grado di chiamare la funzione per ridurre il boilerplate.

    
risposta data 26.08.2013 - 22:34
fonte

Leggi altre domande sui tag