Come decidere cosa forma il sistema in prova

7

Ok, quindi abbiamo iniziato con la versione iniziale di "The Art Of Unit Testing" e facciamo test unitari per classi in cui ogni test copre un aspetto di un metodo.

Questo ha lo svantaggio di costi di manutenzione elevati e test fragili e sembra che la seconda versione di "The Art Of Unit Testing" punti a prendere unità più grandi durante i test.

Qual è la taglia giusta (quella che usi) quando esegui i test unitari? Ho sentito di testare solo l'interfaccia pubblica fornita da un modulo, ma nel progetto che stiamo lavorando abbiamo una relativa piccola superficie pubblica con un back office molto grande quindi non sono sicuro che funzionerebbe come l'Arrange dei test sarebbe davvero grande e probabilmente difficile da seguire.

Quindi, ancora una volta, come impostare i limiti del tuo SUT o in che modo decidi quali sono i tuoi SUT?

    
posta Ignacio Soler Garcia 01.06.2015 - 17:15
fonte

2 risposte

3

Idealmente le cose varierebbero secondo la regola del buon senso. Martin Fowler parla di un'unità come classe (più classi correlate in alcuni casi) e IMHO un'unità dovrebbe essere un utile ammasso di codice, questo può essere un singolo metodo in cui un metodo è piuttosto complesso, o un'intera classe come le classi sono mezzi per dividere un sistema in componenti gestibili.

Un singolo metodo non è generalmente un'unità, in quanto tende ad essere troppo granulare per essere di qualsiasi utilità pratica.

Forse una regola empirica è pensare al test come documentazione: puoi usare i tuoi test come codice di esempio, un modo di usare una parte di funzionalità. Se pensate che un test non abbia senso per nessun altro, poiché i test sono troppo piccoli o banali, è un odore che l'unità testata sia troppo piccola e dovrebbe essere racchiusa in un'unità più ampia. Quindi un metodo complesso potrebbe richiedere molti input possibili e il test li dimostrerebbe, ma una classe di rete (diciamo) avrebbe un test che descriva l'intera classe costruendola, impostando il nome host e la porta e quindi chiamando send o receive metodi su di esso - quei metodi da soli sono inutili da soli.

Solo testare l'interfaccia pubblica ha senso - se non è possibile accedere al codice tramite l'interfaccia pubblica, non c'è una vera ragione per averlo! Tuttavia, tu dici di avere una grande funzionalità di back-office, l'API per accedere alle parti componenti del back-office è ancora un'interfaccia pubblica (cioè pubblica a un client o una classe di computer) e dovrebbe essere considerata per un test unitario in questo riguardo.

    
risposta data 01.06.2015 - 17:52
fonte
3

Non esiste una risposta "taglia unica" a cui dovresti mettere i limiti del tuo SUT.

La dimensione ottimale di un SUT per il test dell'unità dipende da molti fattori, tra cui

  • La lingua e la toolchain con cui stai lavorando (quanti errori possono essere rilevati da analisi statiche / compilazione del codice)
  • La complessità del prodotto che stai creando
  • Quanto è familiare il team nella creazione di un prodotto di questo tipo

Un team che scrive il suo decimo sito web a bassa complessità potrebbe utilizzare SUT molto più grandi nei loro test unitari rispetto a un team che è nuovo al lavoro e / o ha il compito di creare un sito molto complesso.

Scegliere la dimensione del tuo SUT è un atto di bilanciamento. Se è troppo piccolo, i test iniziano a dipendere dalle scelte di implementazione, il che causa la rielaborazione dei test se l'implementazione cambia.
Se è troppo grande, non esiste una correlazione semplice tra "Test A fallisce" e "C'è un problema nella funzione / area B".

Alcune linee guida generali sono:

  1. I test sono un client di una classe, proprio come gli altri moduli che alla fine si interfacciano con esso. I test non dovrebbero avere accesso agli interni di una classe a meno che ciò sia assolutamente necessario per verificare che un particolare requisito sia stato soddisfatto. E anche in questo caso dovresti prima verificare se tale requisito può essere verificato usando solo i membri pubblici della classe.

  2. Ogni test dovrebbe verificare solo un requisito. Spesso questo è travisato come se avesse una sola affermazione in un test. Molto spesso i requisiti non possono essere verificati con una sola affermazione, che porta a persone che scrivono più test in cui ogni test copre solo parte della verifica. Se hai bisogno di più affermazioni assert strettamente correlate per verificare un requisito, allora è perfettamente soddisfacente avere tutto in un solo test.

  3. Dovresti prendere in giro tutte le dipendenze del tuo SUT, a meno che non siano conosciute per essere veloci e ben testate (come classi standard o di terze parti). Quando scrivi le aspettative per questi mock, prova a non fare affidamento sull'ordine in cui sono fatte le chiamate, a meno che l'ordine delle chiamate sia un requisito esplicito.

  4. Concentrati sullo sforzo di test sulle aree ad alta complessità e / o incertezza. C'è molto poco valore nello scrivere un test per un getter a una riga. Per tali funzioni, è molto facile vedere che sono corretti e c'è poco rischio che un cambiamento futuro li romperà.

risposta data 01.06.2015 - 18:11
fonte

Leggi altre domande sui tag