Il test del codice in generale non è facile. Se lo fosse, lo avremmo fatto tutto molto tempo fa, e non ne abbiamo fatto un bel po 'solo negli ultimi 10-15 anni. Una delle maggiori difficoltà è sempre stata nel determinare come testare il codice che è stato scritto in modo coeso e ben fattorizzato e testabile senza interrompere l'incapsulamento. Il principio BDD suggerisce che ci concentriamo quasi interamente sul comportamento, e in qualche modo sembra suggerire che non è davvero necessario preoccuparsi dei dettagli interni in misura così grande, ma questo può spesso rendere le cose abbastanza difficili da testare se ci sono un sacco di metodi privati che fanno "cose" in un modo molto nascosto, in quanto possono aumentare la complessità complessiva del test per gestire tutti i possibili risultati a un livello più pubblico.
La derisione può aiutare in una certa misura, ma di nuovo è piuttosto focalizzata esternamente. La dipendenza dall'iniezione può anche funzionare molto bene, di nuovo con mock o test double, ma questo può anche richiedere l'esposizione di elementi tramite un'interfaccia, o direttamente, che altrimenti avresti preferito rimanere nascosti - questo è particolarmente vero se desideri avere un buon livello di sicurezza paranoico su certe classi all'interno del tuo sistema.
Per me, la giuria non sa ancora se progettare le tue classi per essere più facilmente testabile. Questo può creare problemi se ti trovi a dover fornire nuovi test mantenendo il codice legacy. Accetto che dovresti essere in grado di testare assolutamente tutto in un sistema, eppure non mi piace l'idea di esporre - anche indirettamente - gli interni privati di una classe, solo per poter scrivere un test per loro.
Per me, la soluzione è sempre stata quella di adottare un approccio abbastanza pragmatico e combinare un numero di tecniche per adattarsi a ciascuna situazione specifica. Io uso molti doppi test ereditati per esporre proprietà e comportamenti interni ai miei test. Prendo in giro tutto ciò che può essere allegato alle mie lezioni, e dove non comprometterà la sicurezza delle mie lezioni, fornirò un mezzo per sovrascrivere o iniettare comportamenti ai fini del test. Prenderò in considerazione la possibilità di fornire un'interfaccia più guidata dagli eventi, se contribuirà a migliorare la capacità di testare il codice
Dove trovo il codice "non testabile" , cerco di capire se posso fare il refactoring per rendere le cose più testabili. Dove hai un sacco di codice privato nascosto dietro le quinte, spesso troverai nuove classi in attesa di essere scomposte. Queste classi potrebbero essere utilizzate internamente, ma possono spesso essere testate in modo indipendente con meno comportamenti privati, e spesso successivamente con meno livelli di accesso e complessità. Una cosa che faccio attenzione ad evitare, tuttavia, è scrivere codice di produzione con codice di test integrato. Può essere allettante creare " test lugs " che comporta l'inclusione di tali orrori come if testing then ...
, che indica un problema di test non completamente decostruito e completamente risolto.
Potresti trovare utile leggere il libro xUnit Test Patterns di Gerard Meszaros, che copre tutto questo tipo di cose in modo molto più dettagliato di quanto io possa entrare qui. Probabilmente non faccio tutto ciò che suggerisce, ma aiuta a chiarire alcune delle situazioni di test più difficili da affrontare. Alla fine della giornata, vuoi essere in grado di soddisfare i tuoi requisiti di test mentre stai ancora applicando i tuoi progetti preferiti, e aiuta ad avere una migliore comprensione di tutte le opzioni al fine di decidere meglio dove potresti dover scendere a compromessi.