Un fattore importante che rende estremamente utili i test unitari è feedback rapido .
Considera cosa succede quando la tua app è completamente coperta da test di integrazione / sistema / funzionale (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.
- Apporti una modifica al repository SCM,
- qualche volta (probabilmente giorni) più tardi i ragazzi del test ricevono una nuova versione interna e iniziano a testarla,
- trovano un bug e presentano una segnalazione di bug,
- (nel caso ideale) qualcuno ti assegna il bug report
Tutto ciò potrebbe richiedere giorni o addirittura settimane. A questo punto hai già lavorato ad altre attività, quindi non hai i minimi dettagli del codice scritto in precedenza nella tua mente. Inoltre, in genere non hai alcuna prova diretta di dove sia effettivamente il bug, quindi ci vuole molto tempo per trovare e correggere il bug.
Mentre 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 controllare per quella condizione!"), quindi
- correggi il bug immediatamente.
Tutto ciò accade in una questione di minuti .
Questo non vuol dire che i test di integrazione / sistema non siano utili; servono solo a scopi diversi. Con test unitari ben scritti puoi catturare una grande percentuale dei bug nel codice prima che arrivano alla fase di integrazione, dove è già molto più costoso trovarli e risolverli. Hai ragione che i test di integrazione sono necessari per catturare quei tipi di bug che sono difficili o impossibili da catturare con i test unitari. Tuttavia, nella mia esperienza quelli sono il tipo più raro; la maggior parte dei bug che ho visto sono causati da omissioni semplici o addirittura banali da qualche parte all'interno di un metodo.
Per non parlare del fatto che il test dell'unità verifica anche le interfacce per usabilità / sicurezza ecc., fornendo così un feedback di vitale importanza per migliorare il tuo design e le tue API. Quale IMHO può ridurre considerevolmente le possibilità di errori di integrazione di moduli / susbsystem: più un'API è più semplice e pulita, minori sono le possibilità di incomprensioni o omissioni.
What are you experience with automated unit testing, automated integration testing, and automated acceptance testing, and in your experience what has yielded the highest ROI? and why?
Il ROI dipende da molti fattori, probabilmente il più importante è se il tuo progetto è greenfield o legacy. Con lo sviluppo di greenfield il mio consiglio (e l'esperienza fino ad ora) è di fare un test di unità TDD dall'inizio. Sono fiducioso che questo sia il metodo più efficace in questo caso.
In un progetto legacy, tuttavia, la creazione di una copertura di test unitaria sufficiente è un'impresa enorme che sarà molto lenta a produrre benefici. Se possibile, è più efficiente cercare di coprire le funzionalità più importanti con test di sistema / funzionali tramite l'interfaccia utente. (Le applicazioni desktop GUI potrebbero essere difficili da testare automaticamente tramite la GUI, sebbene gli strumenti di supporto automatico per i test stiano gradualmente migliorando ...). Questo ti dà una rete di sicurezza grezza ma efficace rapidamente. Quindi puoi iniziare a costruire gradualmente i test unitari intorno alle parti più critiche dell'app.
If you had to pick just one form of testing to automated on your next project, which would it be?
Questa è una domanda teorica e la trovo senza senso. Tutti i tipi di test hanno il loro uso nella casella degli strumenti di un buon ingegnere SW, e tutti questi hanno scenari in cui sono insostituibili.