sull'efficacia dei test unitari

3

Quanto sono efficaci i test unitari nella realtà?

Ho l'impressione che ad un certo punto i test unitari si trasformino in test che testano la dipendenza tra l'oggetto sotto test e un altro oggetto. Certo, si possono sempre creare dipendenze astratte usando le interfacce, ma cosa succede quando anche le interfacce devono essere cambiate? Cosa succede se l'unità in prova non si basa più su tali dipendenze?

Se i nostri test falliscono a causa di problemi di dipendenza, vuol dire che sono troppo accoppiati al nostro codice? Inoltre, dobbiamo cambiarli ogni volta che cambiamo le dipendenze? Se succede abbastanza spesso, è un segno che il nostro design è sbagliato?

Tendevo a credere che i test unitari siano un modo efficace per testare la robustezza, ma se sono troppo accoppiati alle dipendenze che i nostri oggetti hanno con altri oggetti (siano espressi come interfacce), portano semplicemente a più sprechi di tempo nel fissare quei test per passare il nuovo design. Mi sbaglio?

Il fatto è che io sono perfettamente consapevole dell'esistenza di strutture di derisione e così via. Questo non è il problema. Il problema è che cosa succede quando cambi l'implementazione del tuo metodo e semplicemente non chiama più il mock, e inizi a vedere un gruppo di luci rosse nel tuo stack di test, perché i tuoi mock non sono chiamati come dovrebbero? Test di unità o di integrazione, qualcosa dovrebbe essere fatto qui, giusto?

Se inizio a scrivere diversi metodi di simulazione per ogni condizione di test che mi piace, cosa succede se decido di cambiare la firma della classe che ho deriso? Tutti i miei test vanno nel cestino, giusto? È normale, può essere evitato? È un problema di progettazione?

    
posta user802232 12.10.2011 - 14:16
fonte

3 risposte

10

La persona che ti ha detto di testare le dipendenze è un test di integrazione piuttosto che un test di unità è davvero corretto. Il test unitario consiste normalmente nella creazione di oggetti fittizi di qualsiasi dipendenza e nel test di una singola Classe come una singola "unità". Stai solo testando che chiama i metodi corretti sulle sue dipendenze e restituisce le cose corrette SE le dipendenze restituiscono le cose corrette. Questo è uno dei buoni motivi per utilizzare le interfacce per le tue classi poiché puoi facilmente creare un mock da un'interfaccia usando, ad esempio, EasyMock.

I test unitari sono molto utili finché sono fatti bene, ma credo che alcune persone li portino troppo lontano. Non hai bisogno della copertura del 100% del codice, ma assicurati che tutto ciò che non è ovviamente corretto sia ragionevolmente testato. Raccomando di aggiungere anche test di sistema per qualsiasi sistema complicato: questi test non derideranno nulla, semplicemente testano il sistema nel suo complesso.

Potresti leggere alcune risposte al link per ottenere il massimo fuori dal test dell'unità.

    
risposta data 12.10.2011 - 14:27
fonte
6

How effective are unit tests in reality?

Dipende dal tuo dominio del problema! Li considero quasi sempre valsa la pena, ti permettono di fare il refector senza paura!

I am under the impression that at some point unit tests turn into tests that test the dependency between the object under test and another object. Sure, one can always abstract dependencies using interfaces, but what happens when even the interfaces should be changed? What if the unit under test no longer relies on those dependencies?

Sei a conoscenza di Test Doubles , che copre anche il mocking? Questo dovrebbe aiutarti a test dell'Unità (e Integrazione) in modo più efficace.

Usando TDD, se la tua interfaccia cambia, in teoria dovresti alterare prima il test per indicare quale dovrebbe essere il risultato desiderato, quindi cambiare il codice effettivo per superare il test. Quindi l'intero ciclo Red - > Green - > Refactor.

If our tests fail because of dependency issues, does it mean they are too coupled to our code? Also, do we have to change them every time when we change the dependencies? If it happens quite often, is this a sign that our design is wrong?

Vedi il mio punto sopra a Test Doubles. Tuttavia, a volte non è possibile o non si desidera utilizzare un doppio di prova. In quel caso stai iniziando a testare l'interazione tra 2+ componenti, che è spesso chiamata Test di integrazione.

I tended to believe that unit tests are an effective way to test ensure robustness, but if they are too coupled to the dependencies that our objects have with other objects (be they expressed as interfaces), it simply leads to more time wasted in fixing those tests to pass the new design. Am I wrong?

Non hai torto, penso che il tuo approccio abbia bisogno solo di alcuni tweet Test Double / Mock / Dependency Injection

NOTE: Someone mentioned that when we test the dependencies between two objects, it is no longer considered unit testing, but rather, integration testing. I don't know what to believe in, any longer

IMO, quella persona è corretta - quei tipi di test sono test di integrazione.

Anche per un pensiero un po 'più avanzato in questo spazio, cerca BDD come approccio complementare ai test unitari

    
risposta data 12.10.2011 - 14:33
fonte
5

Sembri preoccupato per una serie di problemi, proverò ad affrontarlo il più possibile:

I am under the impression that at some point unit tests turn into tests that test the dependency between the object under test and another object. Classi e componenti hanno dipendenze su altre classi e componenti, sì. Quindi abbiamo una situazione in cui il test unitario per il componente A deve testare asserzioni sulla funzionalità di A, e la dipendenza dal componente B dovrebbe essere considerata. In Integration Testing, stiamo testando l'interazione appropriata tra il componente di test A e la sua dipendenza nel componente B. Tuttavia, in veri Test unitari, assumiamo che il comportamento del componente B sia compreso e ben testato.

Possiamo usare un framework Mocking per creare un componente fittizio B che abbia un comportamento predefinito che specifichiamo. Il valore del mocking è che possiamo avere test unitari per scenari specifici del componente A Metodo 2, ad esempio:

  • Test Valore di restituzione del componente A Metodo 2 quando l'argomento passato è 4

  • Valore di restituzione test del componente A Metodo 2 quando l'argomento passato è 4 e il componente di dipendenza mocked B restituisce 12.

  • L'eccezione di test viene lanciata dal componente A Metodo 2 quando il componente di dipendenza mocked B restituisce 15.

  • Etc ...

    I tended to believe that unit tests are an effective way to test ensure robustness, but if they are too coupled to the dependencies that our objects have with other objects (be they expressed as interfaces), it simply leads to more time wasted in fixing those tests to pass the new design. Am I wrong?

Questo potrebbe essere un segno di alto grado di accoppiamento e bassa coesione e violazione della singola responsabilità di una classe se i tuoi test sono straordinariamente complicati e proibitivamente fragili. I test unitari sono meno importanti in questo caso, in quanto i principali problemi di progettazione di base dovrebbero essere affrontati per primi. Ciò sarà più vantaggioso per la qualità del software.

OTOH, se trovi che la maggior parte del comportamento di un componente è in realtà all'interno dei componenti dipendenti, sembra un componente wrapper o un componente pass-through di qualche tipo e la copertura di test di questo componente potrebbe essere eccessiva.

    
risposta data 12.10.2011 - 14:39
fonte

Leggi altre domande sui tag