Ho bisogno di un test unitario se ho già un test di integrazione?


47

Se ho già un test di integrazione per il mio programma e tutti hanno superato, allora ho la sensazione che funzionerà. Quindi quali sono i motivi per scrivere / aggiungere test unitari? Dal momento che devo già scrivere i test di integrazione, mi piacerebbe solo scrivere unit test per le parti che non sono coperte dai test di integrazione.

Quello che so sono i vantaggi del test unitario rispetto al test di integrazione

  • Piccolo e quindi veloce da eseguire (ma l'aggiunta di una nuova unità per testare qualcosa è già testata dal test di integrazione significa che la mia tuta di prova totale diventa più grande e più lunga da eseguire)
  • Individuare il bug più facilmente perché verifica solo una cosa (ma posso iniziare a scrivere unit test per verificare ogni singola parte quando il mio test di integrazione fallisce)
  • Trova bug che potrebbero non essere rilevati nel test di integrazione. ad es. mascheramento / compensazione di bug. (ma se i miei test di integrazione superano tutti, il che significa che il mio programma funzionerà anche se esistono alcuni bug nascosti. Quindi trovare / correggere questi bug non hanno la massima priorità a meno che non inizino a rompere i test di integrazione futuri o causare problemi di prestazioni)

E vogliamo sempre scrivere meno codice, ma i test delle unità di scrittura richiedono molto più codice (principalmente impostare oggetti finti). La differenza tra alcuni dei miei test unitari e dei test di integrazione è che nei test unitari utilizzo un oggetto simulato e nei test di integrazione utilizzo un oggetto reale. Che hanno molte duplicazioni e non mi piace il codice duplicato, anche nei test perché questo aggiunge sovraccarico per cambiare il comportamento del codice (lo strumento refactor non può fare tutto il lavoro tutto il tempo).


Solo per curiosità, quanta copertura hanno i tuoi test di integrazione? Inoltre, se hai una logica complessa, i tuoi test di integrazione li coprono tutti o solo una parte e quali parti, importanti per l'azienda o casuali?
civan,

Questa domanda sembra ambigua. Diciamo che ho un metodo controller Rails che chiama un interattore ( github.com/collectiveidea/interactor ). Ho deciso di scrivere test di integrazione per il mio metodo del controller (perché senza di loro non posso fidarmi che il mio endpoint API funzioni). Ci sono almeno due domande qui: (1) dovrei anche scrivere unit test per i miei metodi del controller (cioè, dovrei scrivere unit test che testano lo stesso comportamento dei miei test di integrazione), e (2) dovrei anche scrivere unit test per il mio interattore? Risponderei a queste due domande in modo diverso in determinati contesti aziendali.
Daniel,

Risposte:


33

Hai esposto buoni argomenti a favore e contro i test unitari. Quindi devi chiederti: " Vedo valore negli argomenti positivi che superano i costi in quelli negativi? " Certamente:

  • Piccolo e veloce è un aspetto piacevole del test unitario, sebbene non sia affatto il più importante.
  • Locating-bug [s] -easier è estremamente prezioso. Molti studi sullo sviluppo di software professionale hanno dimostrato che il costo di un bug aumenta rapidamente man mano che invecchia e scende lungo la pipeline di consegna del software.
  • Trovare bug mascherati è prezioso. Quando sai che un determinato componente ha verificato tutti i suoi comportamenti, puoi usarlo in modi in cui non è stato usato in precedenza, con sicurezza. Se l'unica verifica è tramite test di integrazione, sai solo che i suoi usi attuali si comportano correttamente.
  • Deridere è costoso nei casi del mondo reale, e mantenere la derisione lo è doppiamente. In effetti, quando deridete oggetti o interfacce "interessanti", potreste persino aver bisogno di test per verificare che i vostri oggetti simulati modellino correttamente i vostri oggetti reali!

Nel mio libro, i professionisti superano i contro.


2
Deridere non è più economico nei casi del mondo reale? Stai solo impostando le aspettative su quali messaggi riceve il mock e specificando cosa restituirà.
Dogweather,

10
@Dogweather Mock funziona bene quando viene creato per la prima volta. Col passare del tempo e l'oggetto reale viene modificato, le beffe devono cambiare con esso. 10 anni e 6.000 test unitari lungo la strada, è molto difficile sapere che i tuoi test "di successo" hanno davvero successo.
Ross Patterson,

1
A parte questo, "10 anni e 6.000 test unitari" sono numeri per esperienza personale, non iperbole.
Ross Patterson,

3
Ho iniziato a scrivere test di sviluppo automatizzati (unità e integrazione, ma soprattutto quest'ultimo) nel 2004 o nel 2005 e ho sviluppato una libreria di simulazione avanzata per Java. Molte volte ho visto più test di integrazione rompersi per lo stesso motivo (come una modifica nel DB o una modifica della rete) e talvolta scrivo test di integrazione "di livello inferiore" per componenti riutilizzabili, ma preferisco di gran lunga avere solo test di integrazione. I test unitari isolati con derisione, il più delle volte, non ne valgono la pena; Applico il deridere solo come aiuto per i test di integrazione.
Rogério,

Il tuo ultimo punto elenco sembra contraddire l'argomento che stai facendo. In questo punto elenco si oppone la scrittura di mock inutili, che è un argomento contro la scrittura di unit test per le parti che sono già coperte da test di integrazione. La spinta del tuo argomento, tuttavia, è a favore della scrittura di unit test per le parti che sono già coperte da test di integrazione. Potresti chiarire le tue intenzioni qui @RossPatterson?
Daniel,

8

Non vedo molto valore nel reimplementare un test di integrazione esistente come unittest.

I test di integrazione sono spesso molto più facili da scrivere per applicazioni legacy non tdd perché di solito le funzionalità da testare sono strettamente accoppiate, quindi le unità di test in isolamento (= unittesting) possono essere difficili / costose / impossibili.

> Then what are the reasons to write/add unit tests?

A mio avviso, lo sviluppo basato sui test è più efficace se si scrivono i test unitari prima del codice effettivo. In questo modo il codice che soddisfa i test diventa chiaramente separato con un minimo di riferimenti esterni facilmente verificabili.

Se il codice esiste già senza i test unitari, di solito è molto più impegnativo scrivere i test unitari in seguito perché il codice non è stato scritto per un facile test.

Se fai TDD, il codice è automaticamente facilmente testabile.


2
Se ho un'applicazione legacy senza unit-testse voglio includere unit-testsalcune parti, pensi che sia meglio scrivere prima integration testsil codice legacy. Dopo averlo scritto, puoi scollegare l'accoppiamento stretto e creare funzioni con interfacce che possono essere testate? Dato che hai integration-testgià scritto, puoi verificare ad ogni passaggio del refactoring che la nuova versione del codice funzioni ancora come desideri?
alpha_989,

2
@ alpha_989, questo è molto IMHO e sono aperto a sentire altre idee, ma preferirei i test di integrazione rispetto ai test unitari per il codice legacy. In entrambi i casi, dovresti essere certo che i metodi funzionino correttamente prima di aggiungere qualsiasi tipo di test, ma i Test di integrazione assicurano che le aspettative generali dei metodi funzionino rispetto ai singoli elementi di codice.
Britt Wescott,

5

I test di integrazione devono solo verificare che diversi componenti funzionino insieme come previsto. L'accuratezza della logica dei singoli componenti deve essere verificata mediante test unitari.
La maggior parte dei metodi ha diversi percorsi di esecuzione possibili; pensa a if-then-else, variabili di input con valori inattesi o semplicemente sbagliati, ecc. Di solito gli sviluppatori tendono a pensare solo al percorso felice: il percorso normale che non va storto. Ma per quanto riguarda quegli altri percorsi, hai due opzioni: puoi consentire all'utente finale di esplorare quei percorsi attraverso le azioni che intraprendono nell'interfaccia utente e sperare che non si blocchino l'applicazione, oppure puoi scrivere unit test che affermano il comportamento di quegli altri percorsi e agire ove necessario.


4

Alcuni dei motivi che hai indicato nella tua domanda sono davvero importanti e da soli potrebbero valere in favore del test unitario, ma YMMV. Ad esempio, con quale frequenza esegui la tua suite di test integrata? La mia esperienza con i test integrati è che prima o poi diventeranno così lenti che non li eseguirai ogni volta che effettui una modifica e il tempo tra l'inserimento e il rilevamento di un bug aumenterà.

Inoltre, un grosso errore che potresti fare è fidarti di quello

Find bug that may not be caught in integration test. e.g. masking/offsetting bugs.

non è importante. Ti aspetti che i tuoi utenti trovino i bug per te? Fidarsi delle coperture ottenute da test integrati è pericoloso secondo me, puoi facilmente ottenere un alto% di copertura ma in realtà stai testando molto poco.

Immagino che i riferimenti canonici contro i test integrati siano i post di JBrains:

http://www.jbrains.ca/permalink/integrated-tests-are-a-scam-part-1

nel caso non li avessi già letti.

Infine, IMO il feedback che puoi ottenere dai test unitari per il tuo design è inestimabile. Anche giudicare un progetto in base al sentimento intestinale e basarsi su test integrati può essere un errore.


Non ho davvero quell'articolo. Quindi ci sono molti percorsi di codice e i test di integrazione non possono coprirli tutti ... quindi? Lo stesso vale per i test unitari a meno che le unità non siano così banali da essere inutili.
Casey,

È più simile a un argomento contro la fissazione della copertura del codice rispetto a uno che dovresti scrivere un sacco di test unitari e evitare i test di integrazione.
Casey,

1

Se ti aspetti di dover modificare o refactificare il tuo codice, è essenziale disporre di unit test. Esistono test unitari non solo per dimostrare i bug nel momento in cui il codice viene scritto, ma per mostrare quando compaiono nuovi bug quando viene scritto più codice.

Sì, è molto meglio scrivere prima i test di integrazione e unità, ma è molto utile averli anche se saranno scritti in un secondo momento.


3
Non credo che tu abbia fatto il caso. I test di integrazione rivelerebbero anche bug nel codice, e in effetti sono in grado di rilevare bug che i test unitari non lo faranno.
Casey,
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.