Test di unità automatizzati, test di integrazione o test di accettazione [chiuso]


29

TDD e test unitari sembrano essere il grande rave al momento. Ma è davvero così utile rispetto ad altre forme di test automatizzati?

Intuitivamente immagino che i test di integrazione automatizzata siano molto più utili dei test unitari. Nella mia esperienza, la maggior parte dei bug sembra essere nell'interazione tra i moduli e non tanto la logica effettiva (normalmente limitata) di ogni unità. Inoltre, le regressioni si sono verificate spesso a causa del cambiamento delle interfacce tra i moduli (e delle condizioni pre e post modificate).

Sto fraintendendo qualcosa o perché i test unitari stanno ottenendo tanta attenzione rispetto ai test di integrazione? È semplicemente perché si presume che i test di integrazione siano qualcosa che si possiede e che i test unitari siano la prossima cosa che dobbiamo imparare ad applicare come sviluppatori?

O forse il test unitario produce semplicemente il massimo guadagno rispetto alla complessità di automatizzarlo?

Che esperienza hai con i test di unità automatizzati, i test di integrazione automatizzati e i test di accettazione automatizzati e nella tua esperienza che cosa ha prodotto il ROI più elevato? e perché?

Se dovessi scegliere solo una forma di test da automatizzare sul tuo prossimo progetto, quale sarebbe?

Grazie in anticipo.


Vorrei solo aggiungere un link tardivo ai test di integrazione di JB Rainsberger sono una truffa . Evidenzia molte delle ragioni per cui i test di integrazione sono una falsa economia.
Tim


6
Questo è un altro esempio di chiusura di una domanda che andava benissimo su questo sito quando è stata posta tre anni fa! È davvero fastidioso contribuire a una comunità in cui le regole cambiano e tu butti semplicemente tutte le cose vecchie!
Bjarke Freund-Hansen,

Risposte:


34

Un fattore importante che rende estremamente utili i test unitari è il feedback rapido .

Considera cosa succede quando la tua app è completamente coperta da test di integrazione / Sistema / funzionali (che è già una situazione ideale, lontana dalla realtà nella maggior parte dei negozi di sviluppo). Questi sono spesso gestiti da un team di test dedicato.

  • Commetti una modifica al repository SCM,
  • qualche giorno (forse giorni) dopo, i ragazzi del test ottengono una nuova versione interna e iniziano a testarla,
  • trovano un bug e presentano una segnalazione di bug,
  • (nel caso ideale) qualcuno ti assegna la segnalazione di bug.

Tutto ciò può richiedere giorni o addirittura settimane. A questo punto hai già lavorato su altre attività, quindi non hai in mente i minimi dettagli del codice scritto in precedenza. Inoltre, in genere non hai nemmeno una prova diretta di dove si trova effettivamente il bug, quindi ci vuole molto tempo per trovare e correggere il bug.

Considerando che nel test unitario (TDD)

  • scrivi un test,
  • scrivi del codice per soddisfare il test,
  • il test fallisce ancora,
  • guardi il codice e in genere hai un'esperienza "oops" in pochi secondi (come "oops, ho dimenticato di verificare quella condizione!"), quindi
  • correggi immediatamente il bug.

Tutto ciò accade in pochi minuti .

Questo non significa che i test di integrazione / sistema non siano utili; servono solo a scopi diversi. Con test di unità ben scritti puoi catturare una grande parte dei bug nel codice prima che arrivino alla fase di integrazione, dove è già molto più costoso trovarli e risolverli. Hai ragione sul fatto che i test di integrazione sono necessari per rilevare quei tipi di bug che sono difficili o impossibili da rilevare con i test unitari. Tuttavia, nella mia esperienza quelli sono quelli più rari; la maggior parte dei bug che ho visto sono causati da un'omissione semplice o addirittura banale da qualche parte all'interno di un metodo.

Per non parlare del fatto che i test unitari verificano anche le interfacce per usabilità / sicurezza, ecc., Fornendo così un feedback di vitale importanza per migliorare il design e le API. Quale IMHO può ridurre considerevolmente le possibilità di bug di integrazione modulo / sistema: più facile e pulita è un'API, minore è la possibilità di incomprensioni o omissioni.

Che esperienza hai con i test di unità automatizzati, i test di integrazione automatizzati e i test di accettazione automatizzati e nella tua esperienza che cosa ha prodotto il ROI più elevato? e perché?

Il ROI dipende da molti fattori, probabilmente il principale è se il tuo progetto è greenfield o legacy. Con lo sviluppo del greenfield il mio consiglio (e l'esperienza finora) è quello di fare unit test TDD dall'inizio. Sono fiducioso che questo è il metodo più conveniente in questo caso.

In un progetto legacy, tuttavia, costruire una copertura sufficiente per i test unitari è un'impresa enorme che sarà molto lenta a produrre benefici. Se possibile, è più efficace provare a coprire le funzionalità più importanti con test di sistema / funzionali tramite l'interfaccia utente. (Le app della GUI desktop possono essere difficili da testare automaticamente tramite la GUI, sebbene gli strumenti di supporto automatico dei test stiano gradualmente migliorando ...). Ciò fornisce rapidamente una rete di sicurezza grossolana ma efficace. Quindi puoi iniziare a costruire gradualmente unit test intorno alle parti più critiche dell'app.

Se dovessi scegliere solo una forma di test da automatizzare per il tuo prossimo progetto, quale sarebbe?

Questa è una domanda teorica e la trovo inutile. Tutti i tipi di test hanno il loro uso nella cassetta degli attrezzi di un buon ingegnere SW, e tutti questi hanno scenari in cui sono insostituibili.


2
+1 per "feedback rapido" per test unitari. Inoltre, molto utile per l'esecuzione come post-commit su un server di integrazione continua.
Frank Shearar,

1
"Tutti i tipi di test hanno il loro uso nella cassetta degli attrezzi di un buon ingegnere SW, e tutti questi hanno scenari in cui sono insostituibili." - Vorrei poter votare più volte proprio per quello! Le persone che pensano di poter trovare uno strumento / metodo di prova ideale e applicarlo ovunque mi stanno logorando.
ptyx,

8

Tutti i tipi di test sono molto importanti e assicurano che i diversi aspetti del sistema siano nelle specifiche. Quindi, per lavorare all'indietro, "Se dovessi scegliere un tipo di test ..." Non lo farei. Il test unitario mi fornisce un feedback diverso rispetto al test di integrazione o al test interattivo di una persona.

Ecco il tipo / vantaggio dei test che facciamo:

  • Test delle unità: garantisce che le unità eseguano il lavoro come previsto. Testiamo sia i contratti dei fornitori che quelli dei consumatori per ogni interfaccia e questo è abbastanza facile da automatizzare. Controlliamo anche le nostre condizioni al contorno, ecc.
  • Test di integrazione: garantisce che le unità lavorino insieme in concerto. Questo è principalmente per testare il nostro design. Se qualcosa si rompe qui, dobbiamo regolare i nostri test unitari per assicurarci che non accada di nuovo.
  • Test di sistema: garantisce che il sistema soddisfi i requisiti / le specifiche. Di solito le persone fanno questo tipo di test.
  • Test di accettazione: il client esegue questa operazione per verificare che il prodotto finale esegua ciò che viene pubblicizzato.

Test facoltativi ma consigliati:

  • Test dell'esperienza utente: mentre otteniamo un feedback decente dai test di sistema, avere persone dal client in anteprima alcune pre-release possono davvero aiutare a determinare se dobbiamo cambiare le cose prima che sia troppo tardi.

Solo per capire perché Unit Testing presenta un vantaggio rispetto ai test di integrazione, è necessario comprendere gli ordini di grandezza di test aggiuntivi che è necessario essere completi. Per ogni possibile risultato per l'unità A, è necessario un test. Lo stesso per l'unità B. Ora, se entrambi lavorano insieme per una soluzione più completa, il numero di test è combinatorio. In breve, per testare ogni permutazione di interazione tra l'unità A e l'unità B, sono necessari i test A * B. Aggiungi in unità C, e il numero di test per il trio sarebbe A * B * C.

È qui che il concetto di interfacce e confini dell'oggetto diventa molto importante. Le interfacce rappresentano un determinato contratto. Un implementatore di un'interfaccia concorda sul fatto che si comporterà in un certo modo. Allo stesso modo, un consumatore di un'interfaccia concorda sul fatto che utilizzerà l'implementazione in un certo modo. Scrivendo un test che raccoglie tutte le classi che implementano un'interfaccia, è possibile verificare facilmente che ogni implementazione osservi i contratti di interfaccia. Questa è metà dell'equazione. L'altra metà è quella di testare il lato consumatore, che è il luogo in cui entrano in gioco gli oggetti finti. La simulazione è configurata per garantire che le interazioni siano sempre nelle specifiche. A questo punto, tutto ciò che serve sono alcuni test di integrazione per assicurarsi che i contratti tra implementatore / consumatore siano corretti.


"Test di sistema: garantisce che il sistema soddisfi i requisiti / le specifiche Solitamente le persone eseguono questo tipo di test". I test di integrazione di sistema / aka funzionali / aka "end-to-end" / aka di alto livello sono buoni anche per l'automazione.
MiFreidgeim SO-smetti di essere malvagio il

3

Questi sono strumenti diversi con obiettivi diversi:

  • Il test unitario è uno strumento di progettazione (TDD) e un prerequisito per il refactoring.

  • I test di integrazione sono ottimi per visualizzare lo stato di avanzamento del progetto e anche per evitare bug di regressione.

Il punto da ricordare è che non puoi davvero progettare con i test di integrazione e non troverai regressioni con i test unitari.


Non puoi davvero progettare con i test di integrazione e non troverai regressioni con i test unitari. Esattamente!
Chankey Pathak,

I test unitari possono trovare regressioni causate dal refactoring, ad esempio un metodo di supporto condiviso modificato. Tuttavia, i test di integrazione sono molto migliori.
Stuper Utente

Il secondo punto sui test di integrazione include i test "sistema / funzionali" (aka "end-to-end")
MiFreidgeim SO-stop essere malvagio

Pienamente concordato; un punto simile è stato sollevato alcuni anni fa da Steve Sanderson. Vedi la tabella "Obiettivo - Tecnica più forte" nel suo post del blog 2009 su blog.stevensanderson.com/2009/08/24/… per pensieri un po 'complementari ai tuoi qui.
Mark A. Fitzgerald,

1

Ho usato ampiamente il selenio per i controlli di integrità.

In una grande società di editoria Web, quando è stata rilasciata una nuova versione, in genere ci sono voluti circa 3 tester circa un'ora o due per visitare tutte le famiglie di siti e assicurarsi che tutto fosse OK, secondo lo script di test. Con Selenium, siamo stati in grado di automatizzare i test e distribuirli su più macchine e browser. Attualmente, quando vengono eseguiti gli script di test, sono necessari 3 PC per circa 10 minuti per fare automaticamente la stessa cosa E emettere un bel rapporto.

Il bello del selenio è che puoi collegarlo a framework di unit test come XUnit, TestNG o MSTest.

Nella mia esperienza, è stato estremamente prezioso, tuttavia la configurazione di qualcosa del genere dipende molto dal tuo progetto e dal tuo team, quindi il ROI varierà sicuramente.


1

Il ROI migliore è in genere il primo test in grado di trovare quel tipo di bug.

I test unitari dovrebbero trovare la maggior parte dei bug che si trovano solo in un metodo o forse in un componente. Trova i bug che di solito possono essere risolti in pochi minuti, con tempi di rotazione totali inferiori a un'ora. Test MOLTO economici, bug MOLTO economici da trovare e correggere! Se questi bug sono diventati test di integrazione, il turn-around potrebbe essere più simile a un giorno (le esecuzioni dei test spesso si verificano di notte), supponendo che il bug non sia occluso da un altro bug; inoltre è probabile che vengano introdotti più bug poiché è stato scritto altro codice rispetto al codice buggy iniziale; inoltre qualsiasi riprogettazione avrà un impatto su più parti di codice. Inoltre, lasciare passare più bug significa dover fare molte più esecuzioni di test prima che il test di integrazione possa essere completato. I test di unità scadenti sono spesso al centro di lunghi, onerosi, costositest dei cicli di integrazione. Saltare i test unitari potrebbe dimezzare i tempi di sviluppo, ma i test impiegheranno almeno 3-4 volte il tempo, l'intero progetto raddoppierà in lunghezza e si avrà comunque una qualità inferiore rispetto a un test IME unitario.

Il test di integrazione è in genere il primo test effettivo in grado di trovare bug di integrazione (sebbene i processi di revisione possano trovare alcuni bug prima che il software venga scritto o prima che il codice vada a testare). Volete trovare quei bug prima di iniziare a mostrare il software all'utente o rilasciarlo, dato che correggere i bug all'ultimo momento (o hot-fix!) È molto costoso. Non è possibile trovare quei bug in precedenza, quando sarebbero più economici da correggere, poiché per l'integrazione sono necessari più componenti funzionanti (per definizione). I test di integrazione vengono rallentati quando i bug che non hanno nulla a che fare con pezzi interagenti (come errori di battitura minori) devono essere risolti prima ancora che possano iniziare i test più interessanti.

Il test di accettazione da parte dell'utente sta assicurando che il software faccia ciò che il cliente desidera (anche se si spera che sia stato coinvolto per tutto il tempo, per ridurre il rischio di trovare un enorme divario tra aspettative e software effettivo alla fine del progetto - MOLTO costoso !). Quando arriverai a questa fase di test, dovresti davvero credere che la maggior parte dei bug nel tuo prodotto, almeno rispetto alle specifiche, siano già stati trovati. I test di accettazione da parte dell'utente riguardano più la sicurezza del prodotto che le esigenze del cliente che l'assenza di bug rispetto alle specifiche.

Se avessi solo intenzione di automatizzare un tipo di test, sarebbe un test unitario. I test di integrazione possono essere eseguiti manualmente e sono stati eseguiti in questo modo da molte grandi aziende per anni. È più dispendioso in termini di tempo eseguire manualmente il lavoro che potrebbe essere svolto ripetutamente da un computer e molto più costoso per la maggior parte dei progetti, per non parlare di noioso e soggetto a errori, ma può essere fatto. I test di accettazione dell'utente sono spesso manuali, poiché gli utenti spesso non sanno come automatizzare i loro test mentre continuano a testare ciò a cui tengono. I test unitari DEVONO essere automatizzati. È necessario essere in grado di eseguire tutti i test unitari in pochi secondi su richiesta con frequenza ogni pochi minuti. Gli umani non riescono nemmeno ad avvicinarsi ai test manuali. Per non parlare del fatto che i test unitari sono nel codice e non possono essere eseguiti senza chiamarli attraverso il codice, cioè automatizzandoli.

Una cosa da tenere a mente è che questo è un forum principalmente per sviluppatori, non per tester. I test di integrazione sono implementati principalmente dai tester. I test unitari sono implementati dagli sviluppatori. Naturalmente, gli sviluppatori parlano più di unit test che di altri tipi di test. Questo non significa che non pensano che altri test siano importanti. Significa solo che in realtà non lo fanno (o lo fanno meno spesso).


Grazie soprattutto per l'ultimo paragrafo, non ci ho pensato.
Bjarke Freund-Hansen,

Cordiali saluti, ho aggiornato la risposta da quando l'hai letta - ho capito che non avevo letto abbastanza attentamente la domanda originale
Ethel Evans,

@EthelEvans, le tue ragioni sulle priorità dei test unitari sono corrette per i nuovi progetti. Per i progetti legacy, scritti senza pensare all'automazione della copertura dei test, i test di integrazione di sistema / aka funzionali / aka di alto livello sono i più importanti. Vedi l'ultima parte della risposta programmers.stackexchange.com/a/39370/31574 .
MiFreidgeim SO-smetti di essere malvagio il

@MichaelFreidgeim, dipende in definitiva dalla stabilità delle interfacce. L'automazione di test di alto livello può comportare rapidamente costi di manutenzione proibitivi se non vengono aggiornati rapidamente. In questo caso, automatizzare in basso per aiutare a costruire la stabilità e utilizzare i test esplorativi (possibilmente basati su liste di controllo o di sessione) per E2E e test di integrazione per evitare costi di manutenzione dell'automazione fastidiosi. Tuttavia, non tutti i progetti legacy hanno interfacce stabili, specialmente se vengono rifattorizzati o riprogettati in modo aggressivo.
Ethel Evans,

1

Sento che i test di accettazione sono i re in questo scenario.

Se un commit interrompe i test di accettazione, deve essere risolto.

I test di accettazione indicano dove si trova il software, i test unitari no.

Pertanto i test unitari possono fornire un falso senso di sicurezza.


0

La domanda non è tanto ciò che è più importante, quanto ciò che può essere automatizzato ed eseguito rapidamente.

I test unitari mostrano se un componente piccolo è adatto allo scopo in un modo particolare e in genere è piccolo e veloce da eseguire. Essendo piccoli, di solito sono ragionevolmente facili da automatizzare.

I test di integrazione mostrano se i componenti funzionano insieme. Di solito sono molto più grandi e potrebbero non essere facili da automatizzare. Possono richiedere più tempo per l'esecuzione. È utile poterli eseguire automaticamente, ma è un compito più grande e comunque non verranno eseguiti altrettanto spesso.

I test di accettazione mostrano se un progetto è accettabile o meno. Questo è normalmente impossibile da automatizzare completamente (anche se i test automatici possono svolgere un ruolo), dal momento che è normalmente impossibile stabilire i requisiti esatti e completi in una questione formale che è meno complicata del codice sorgente stesso. I test di accettazione di solito includono potenziali utenti che fanno cose con il sistema e osservano che i risultati sono soddisfacenti sotto tutti gli aspetti, che è in parte parzialmente soggettivo. Poiché i test di accettazione vengono in genere eseguiti una volta (diversi clienti vorranno di norma eseguire i propri test di accettazione separati) non vale la pena automatizzare.

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.