Il vero problema qui è che hai semplificato tutto il significato del tuo codice. Tutto ciò che rimane è una rappresentazione strutturale. Vuoi che rispondiamo in base alla struttura in modo che tu abbia una regola basata sulla struttura per seguire ciecamente senza dover pensare al significato, al contesto o alla semantica.
Non che non vorrei sapere una regola del genere se esistesse. So solo che non funziona e ho smesso di guardare molto tempo fa.
Ma se mi stai facendo questa domanda, penso di sapere dove ti trovi, quindi lascia che ti indichi alcune buone indicazioni:
If I am testing func a()
Se tutto ciò che vuoi è testare, puoi testare a()
eseguendo qualsiasi codice che lo usi. Onestamente, qualsiasi codice. Puoi farlo a mano. Se in realtà vuoi dire che vuoi creare alcuni test automatici allora ...
should I mock all the other function calls within that method or only mock the dependencies I have outside of this class altogether? For example, mocking database calls, etc.
Velocità
Considera quanto sia tragico mescolare un test che impiega 0,01 secondi per essere eseguito con un test che impiega 3 minuti perché ora impiegano complessivamente 180,01 secondi per l'esecuzione.
Ne parlo perché quando leggi articoli sui test e si vantano che hanno impedito a un test di colpire il database, la lezione non "non ha mai colpito il DB con un test". È "il mio DB era lento, quindi ho capito come farne a meno durante il test di altre cose, puoi farlo anche tu".
Quindi quando mi chiedi cosa fare con a(b(c(d(e()))))
la mia risposta è testare TUTTO ma prendi in giro le cose lente e metti quei test veloci in una pila diversa.
Se d()
è lento, per qualsiasi motivo, (DB, filesystem, calcolatore di numeri primi, o web cam di una lampada di lava che genera random) quindi mock d()
.
Per lento intendo a()
b()
c()
e e()
sono incredibilmente veloci per confronto. Tanto che vivrebbero nella tua pila di test "eseguimi ogni volta".
Il punto di derisione d()
non è che utilizza un test malvagio che odia DB. È che ti impedisce di testare altre cose rapidamente.
Questi test rapidi sono così utili che molti IDE ti permetteranno di eseguirli senza fare clic su nulla. Eseguono mentre scrivi come il compilatore di IDE quando dà suggerimenti e sottolinei cose a causa di un errore del compilatore. È come se i test rapidi diventassero parte del tuo compilatore.
Anche gli errori del compilatore sono veloci, quindi perché non dovrebbero essere nella pila veloce?
Basta mantenere le prove lente. Non so voi ma odio aspettare mentre sto digitando.
La leggibilità
Sono favorevole a piccoli test isolati. Ma non perché credo che ogni classe e metodo abbia bisogno del suo test. In realtà odio quell'idea. Scoraggia la decomposizione. No, quello che voglio sono piccoli test che limitano ciò che sento di dover leggere per capire a()
. È così. I miei limiti di test riguardano esclusivamente la lettura del codice. Non riguardo la sua struttura. Diamine, mi interessa solo la velocità del test perché rallenta la lettura. Si tratta di leggere. Perché? Perché se riesco a leggerlo facilmente so se funziona. Aggiungo test per rendere il codice di lettura più veloce.
Dovresti prendere in giro b()
durante il test di a()
? Se sono entrambi veloci, quanto è difficile capire a()
con b()
che vivono al suo interno? Non modificherei b()
a meno che la leggibilità non lo richieda. Ciò significa che puoi testare: a(b(c(dMock(e()))))
e farla finita, se sei sicuro che i neofiti potranno seguirlo. Se non riescono a continuare a scomporlo più piccolo finché non possono. Considera sempre i neofiti.
C'è un tipo di considerazione strutturale degna di nota qui, ma è ancora un problema di leggibilità. Le cose pubbliche hanno molti clienti mentre i privati ne hanno pochi. Sono molto più propenso a isolare b()
per i test e rendere chiaro l'uso previsto se è pubblico. Sembra ovvio, ma la ragione è questa: se devo controllare ogni bit di codice che lo utilizza, questo è un sacco di codice da leggere. Ma le funzioni private assorbono molta pressione.
Funzioni
Avrai notato che ora ho davvero ignorato il fatto che sono funzioni. Non mi interessa davvero se sono funzioni, oggetti, chiusure o subroutine. Posso riscrivere a()
per fare tutto questo senza funzioni. Ciò che conta è la segregazione della velocità e della leggibilità del test. Mi piacerebbe rompere a()
se stesso in più funzioni se questo mi porterebbe a.
Tipi di test
Potresti aver notato anche che non ho chiamato nulla di unit test o test di integrazione. Questo perché ora ho letto abbastanza spiegazioni conflittuali su questi nomi che sono stufo di cercare di spiegare cosa intendo davvero quando li uso. C'è un mucchio di test lento e un mucchio di test veloce. Puoi chiamarli Alice e Bob per quello che mi interessa.
Bene, lo riprendo. Qualunque cosa tu faccia, per favore dai loro nomi migliori allora.