Questa è una distinzione importante, ma sfortunatamente non troverai mai un accordo. Il problema è che la maggior parte degli sviluppatori li definisce dal proprio punto di vista. È molto simile al dibattito su Plutone. (Se fosse più vicino al Sole, sarebbe un pianeta?)
Il test unitario è facile da definire. Verifica il CUT ( Code Under Test ) e nient'altro. (Beh, il meno altro possibile.) Ciò significa beffe, falsi e infissi.
All'altra estremità dello spettro c'è quello che molte persone chiamano test di integrazione del sistema . Questo è il test il più possibile, ma è ancora alla ricerca di bug nel tuo CUT.
Ma che dire della vasta distesa tra?
- Ad esempio, cosa succede se si esegue il test solo un po 'di più rispetto al CUT? E se includessi una funzione di Fibonacci, invece di usare un apparecchio che ti aveva iniettato? Definirei quel test funzionale , ma il mondo non è d'accordo con me.
- E se includi
time()
o rand()
? O se chiami http://google.com
? Chiamerei quel test di sistema , ma ancora una volta sono solo.
Perché è importante? Perché i test di sistema non sono affidabili. Sono necessari, ma a volte falliranno per ragioni indipendenti dalla tua volontà. D'altra parte, i test funzionali dovrebbero sempre passare, non fallire in modo casuale; se sono veloci, potrebbero anche essere utilizzati dall'inizio per utilizzare lo sviluppo guidato dai test senza scrivere troppi test per l'implementazione interna. In altre parole, penso che i test unitari possano essere più un problema di quanto valgano, e ho una buona compagnia .
Ho messo i test su 3 assi, con tutti i loro zero al test unitario :
- Test funzionali: utilizzo del codice reale sempre più in profondità nello stack di chiamate.
- Test di integrazione: sempre più in alto il tuo stack di chiamate; in altre parole, testare il tuo CUT eseguendo il codice che lo userebbe.
- Test di sistema: operazioni sempre più irripetibili (scheduler O / S, clock, rete, ecc. )
Un test può essere facilmente tutti e 3, a vari livelli.