Una cosa sui test automatizzati è che richiede di scrivere codice per essere testabili. Questa non è una cosa cattiva in sé e per sé (in effetti è buona perché scoraggia molte pratiche che come regola dovrebbe essere evitata), ma se stai cercando di applicare i test unitari al codice esistente, allora è probabile che non lo sia stato scritto in modo verificabile.
Cose come singoli, metodi statici, registri, localizzatori di servizi e così via introducono dipendenze che sono molto difficili da deridere. Le violazioni della Legge di Demetra significano che troppe parti della tua base di codice sanno troppo su come funzionano altre parti della tua base di codice, introducendo ulteriori dipendenze nascoste che possono essere difficili da rompere. Tutte queste cose rendono difficile isolare un modulo dal resto della base di codice e se non riesci a testare i tuoi moduli in isolamento, i test unitari perdono molto del loro valore. Se un test ha esito negativo è a causa di un errore nell'unità in prova, o a causa di un errore in una delle sue dipendenze, o forse è perché i dati che vengono trasferiti attraverso un'origine dati dipendente non sono quelli previsti dal test writer ? Se puoi'
La maggior parte delle codebase che ho visto che non sono state costruite pensando ai test unitari tendono ad essere intrinsecamente non verificabili, poiché i programmatori tendono a concentrarsi sul far funzionare il codice come si aspettano, piuttosto che fare il lavoro necessario per mantenere l'accoppiamento libero e le dipendenze esplicite . Il codice che è stato scritto pensando ai test unitari tende ad apparire molto diverso.
Molte persone adottano un approccio ingenuo ai test unitari quando iniziano a farlo per la prima volta, pensano di poter semplicemente scrivere un sacco di test per una base di codice esistente e tutto andrà bene, ma non funziona mai così a causa di i problemi sopra menzionati. Iniziano a scoprire di dover disporre di quantità eccessive di configurazione nei test unitari per farli funzionare affatto, e i risultati sono spesso discutibili perché la mancanza di isolamento nel codice significa che non è possibile rintracciare ciò che ha causato un fallimento del test. Tendono anche a iniziare a provare test "intelligenti" che dimostrano alcuni aspetti altamente astratti di come dovrebbe funzionare il sistema. Questo tende a fallire perché un test di unità "intelligente" è una potenziale fonte di bug in sé. Il test ha avuto esito negativo a causa di un bug nel modulo testato, o a causa di un bug nel test? Un test dovrebbe essere così lancinante semplice che ovviamente non c'è alcuna possibilità che un bug possa nascondersi al suo interno. In effetti i test migliori sono raramente più lunghi di 2 righe, la prima riga indica all'unità sottoposta a test di fare qualcosa, la seconda afferma che ciò che ha fatto è stato quello che ci si aspettava.
Se il tuo team è seriamente intenzionato ad adottare i test unitari, non sarebbe saggio iniziare con un progetto esistente. I progetti esistenti del tuo team sono probabilmente non verificabili senza importanti refactoring. Stai meglio usando un nuovo progetto come base per apprendere i test unitari, dato che hai una lavagna pulita con cui lavorare. È possibile progettare la nuova base di codice per favorire l'iniezione di dipendenze su singoli, registri e altre dipendenze nascoste, è possibile scrivere per dipendere dalle interfacce anziché dalle implementazioni e così via. Puoi anche (e dovresti) scrivere i test a fianco del codice da testare, poiché la scrittura dei test in seguito porta a test unitari che assicurano che il modulo testato faccia quello che pensi possa essere fatto invece di quelli che testano che lo fa cosa dicono le specifiche che dovrebbe fare.
Una volta acquisita una certa confidenza con i test unitari, il tuo team probabilmente inizierà a rendersi conto dei difetti nel loro codice esistente che costituiranno ostacoli ai test unitari. Questo è quando puoi iniziare a lavorare per refactificare il codice esistente per renderlo più testabile. Non essere ambizioso e cerca di farlo tutto in una volta, o prova a sostituire un sistema che funziona con uno completamente nuovo, inizia semplicemente trovando i bit della base di codice che possono essere facilmente testati (quelli che non hanno eventuali dipendenze o dove le dipendenze sono ovvie) e scrivere test per quelle. So di aver detto che scrivere un test a fianco del codice è preferibile a scrivere test dopo, ma anche un test scritto in seguito ha ancora valore come punto di partenza. Scrivi i test come se non sapessi nulla su come funziona la classe oltre a ciò che le sue specifiche dicono che dovrebbe fare. Quando si eseguono i test e si verificano errori, le specifiche o l'implementazione sono errate. Ricontrolla entrambi per determinare quale è sbagliato e aggiorna il test o il codice di conseguenza.
Una volta che hai raccolto il frutto basso, inizia il tuo vero lavoro. Devi iniziare a trovare le dipendenze nascoste nella tua base di codice e correggerle, una alla volta. Non diventare troppo ambizioso a questo punto, basta attenersi a fare un modulo alla volta, o anche solo un singolo problema in un modulo, fino a quando gli ostacoli al test non vengono risolti e puoi passare al bit successivo.
TL: DR: la maggior parte delle persone pensa che i test siano facili e che tu possa adattarli facilmente al codice esistente. Entrambe queste ipotesi sono sbagliate. Se ti imbarchi in un progetto per ottenere unit testing nei tuoi progetti tenendo conto di entrambi questi fatti, avrai maggiori probabilità di avere successo.