L'aggiunta di unit test ha senso per il noto codice legacy?


21
  • Sto parlando di unit test in senso TDD. (Non "integrazione" automatizzata, o come ti piace chiamarlo test.)
  • Codice legacy come in: (C ++) codice senza test. (vedi: Michael Feathers ' lavora in modo efficace con il codice legacy )
  • Ma anche il codice legacy come in: codice con cui il nostro team ha lavorato negli ultimi 10-5 anni, quindi molto spesso abbiamo una buona idea di dove mettere le cose per cambiare qualcosa.
  • Disponiamo di test unitari (tramite Boost.Test) per alcuni moduli che sono arrivati ​​in seguito o si sono adattati "in modo naturale" ai test unitari (contenitori specifici per app comuni, stringhe, aiutanti di rete, ecc.)
  • Non disponiamo ancora di test di accettazione automatici adeguati.

Ora, recentemente ho avuto il "piacere" di implementare 3 nuove funzionalità rivolte all'utente.

Ognuno di questi mi ha richiesto circa 1-2 ore per aggiornarmi con le parti di codice che dovevo cambiare, 1-2 ore per implementare il (piccolo) codice che avevo bisogno di cambiare e altre 1-2 ore per assicurarmi che l'app corse correttamente dopo e fece come doveva fare.

Ora ho davvero aggiunto poco codice. (Penso che un metodo e alcune linee telefoniche per ogni funzione.)

La stesura di questo codice (tramite uno dei metodi suggeriti in WEwLC ), in modo che un test unitario avesse senso (e non fosse una tautologia completa) avrebbe richiesto facilmente altre 2-4 ore, se non di più. Ciò avrebbe aggiunto il 50% -100% di tempo a ciascuna funzionalità, senza alcun vantaggio immediato

  1. Non avevo bisogno del test unitario per capire qualcosa sul codice
  2. Il test manuale è lo stesso lavoro, poiché devo ancora verificare se il codice è integrato correttamente nel resto dell'app.

Concesso, se , in seguito, "qualcuno" è arrivato e ha toccato quel codice, teoricamente potrebbe trarre qualche beneficio da quel test unitario. (Solo teoricamente, poiché quell'isola testata di codice vivrebbe in un oceano di codice non testato.)

Quindi, "questa volta" ho scelto di non fare il duro lavoro di aggiungere un test unitario: le modifiche al codice per ottenere quelle cose sotto test sarebbero state significativamente più complesse delle modifiche al codice per ottenere la funzionalità correttamente (e pulita).

È qualcosa di tipico per il codice legacy fortemente accoppiato? Sono pigro / stabiliamo le priorità sbagliate come squadra? O sono prudente, testando solo cose in cui il sovraccarico non è troppo elevato?


cosa succederebbe se qualche altro dipartimento prendesse il sopravvento sul "ben noto codice legacy"? Cosa ci faranno i ragazzi lì?
Alex Theodoridis,

Risposte:


18

Devi essere pragmatico su queste situazioni. Tutto deve avere un valore commerciale, ma l'azienda deve fidarsi di te per giudicare quale sia il valore del lavoro tecnico. Sì, c'è sempre un vantaggio nell'avere test unitari, ma è abbastanza grande da giustificare il tempo impiegato?

Discuterei sempre su un nuovo codice ma, su un codice legacy, devi fare una chiamata di giudizio.

Ti trovi spesso in quest'area di codice? Quindi c'è un caso di miglioramento continuo. Stai apportando un cambiamento significativo? Quindi c'è un caso che è già un nuovo codice. Ma se stai creando un codice di una riga in un'area complessa che probabilmente non verrà toccata di nuovo per un anno, ovviamente il costo (per non parlare del rischio) della riprogettazione è troppo grande. Basta schiaffeggiare la tua riga di codice e fare una doccia veloce.

Regola empirica: pensa sempre a te stesso: " Credo che il business tragga maggiori benefici da questo lavoro tecnico che ritengo di dover fare rispetto al lavoro che mi hanno chiesto quale sarà ritardato di conseguenza? "


Qual è un buon pezzo di codice? Uno che è ben progettato, testato, documentato e a prova di futuro o uno per il quale sei pagato? Come sempre: puoi averlo bene ; puoi averlo a buon mercato ; puoi averlo veloce . Scegli uno qualsiasi, il terzo è il tuo costo.
Sardathrion - Ripristina Monica il

2
"Discuterei sempre sul nuovo codice" ... "nuovo codice" in una base di codice legacy o "nuovo nuovo codice"? :-)
Martin Ba,

pdr ha l'idea giusta. È una decisione ingegneristica (una con compromessi). In genere, se si dispone di un grosso codice di controllo, è una buona idea lasciarlo da solo. Ho visto uno sforzo TDD sul codice legacy (solo un anno, ma è abbastanza) alla fine è costato mesi e ha finito per spendere soldi e rompere un'app legacy per mesi fino a quando i bug introdotti dal refactor TDD sono stati corretti. Se il codice / funzionalità è stato eseguito e testato, non andare oltre per aggiungere la strumentazione (TDD) per dirti qualcosa che già sapevi comunque (che funziona).
anon

10

Il vantaggio dei test unitari in senso TDD è ottenere qualcosa che si regge da solo, senza la necessità di una tradizione orale costruita negli anni da un team stabile.

È una grande fortuna che lo stesso team faccia parte dello stesso progetto da così tanto tempo. Ma questo alla fine cambierà. Le persone si ammalano, annoiano o promosse. Si muovono, vanno in pensione o muoiono. I nuovi arrivano con nuove idee e l'impulso di riformattare tutto come hanno imparato a scuola. Le aziende vengono vendute e acquistate. Le politiche di gestione cambiano.

Se vuoi che il tuo progetto sopravviva, devi prepararlo per le modifiche.


3

La scrittura di test unitari rende il codice a prova di futuro. Se la base di codice non ha test, allora dovresti aggiungere nuovi test per tutte le nuove funzionalità perché rende quel pezzo di codice solo un po 'più robusto.

Trovo che l'aggiunta di test, anche nel codice legacy, sia vantaggiosa nel medio-lungo periodo. Se la tua azienda non si preoccupa del medio-lungo termine, cercherei un'altra società. Inoltre, non credo che il test manuale richieda più tempo di quello necessario per scrivere un test unitario impostato. In tal caso, è necessario esercitarsi nel codice kata incentrato sulla scrittura di test.


1
Ma, ma, ma! :-) Quel poco dovrebbe tradursi in un aumento del 100% del tempo necessario per implementare una nuova funzionalità. Essa non diminuire il tempo necessario per implementare le funzioni successive. Si può diminuire il tempo necessario quando si cambia roba.
Martin Ba,

3
Stai assicurando che i cambiamenti in quell'area del codice non introducano nuovi bug, che i nuovi (utenti meno esperti) possano avere una chiara comprensione del codice e che gli effetti collaterali che interessano quell'area siano tossiti al momento del test anziché al rilascio tempo. I test aiutano a verificare che il codice faccia quello che dovrebbe, non facilita l'aggiunta di funzionalità in seguito. Trovo che l'aggiunta di test, anche nel codice legacy, sia vantaggiosa nel medio-lungo periodo . Se la tua azienda non si preoccupa del medio-lungo termine, cercherei un'altra società.
Sardathrion - Ripristina Monica

1
@Martin perché chiaramente quello che fai è codificare ciò che pensi che dovrebbe essere la funzionalità, e quindi spedirlo. Nessun test viene eseguito affatto in qualsiasi fase ... no, aspetta. Come sviluppatori, testiamo tutti il ​​nostro codice (almeno a mano) prima di dire che è fatto. Sostituire "a mano" con "scrivendo un test automatico" non è un aumento del 100% nel tempo. Spesso trovo che si tratti dello stesso tempo impiegato.
Kaz Dragon,

1
@Kaz - "Sostituire" a mano "con" scrivendo un test automatizzato "non è un aumento del 100% nel tempo. Spesso trovo che si tratti dello stesso tempo impiegato". - YMMV, ma per la mia base di codice, questo è chiaramente sbagliato (come indicato nella domanda).
Martin Ba,

3
@Kaz: Quello che volevo dire :-) era: un test unitario verifica il mio codice in modo isolato. Se non scrivo un test unitario non collaudo il codice separatamente, ma solo se il codice viene chiamato correttamente e produce il risultato desiderato nell'app. Questi due punti (chiamati correttamente e app fa quello che dovrebbe) devo testare comunque (manualmente) e non sono coperti da un test unitario. E il test unitario non coprirebbe questi due punti ma "testerebbe" la mia funzione in modo isolato. (E questo test unitario sarebbe aggiuntivo e non sarebbe compensato da nulla per quanto posso vedere.)
Martin Ba

2

Certamente le migliori pratiche impongono di testare l'unità di qualsiasi codice modificato. La codifica nel mondo reale comporta tuttavia molti compromessi, tempo e materiali sono limitati.

Quello che devi fare è valutare il costo in termini reali di risoluzione dei bug e di apportare modifiche senza unit test. È quindi possibile valutare l'investimento nella creazione di tali test. I test unitari riducono notevolmente il costo dei lavori futuri, ma ora hanno un prezzo.

In conclusione, se il sistema viene modificato raramente, potrebbe non valere la pena scrivere unit test, ma se è soggetto a modifiche regolari, ne varrà la pena.


1

Tutte queste piccole decisioni razionali per non creare test stanno accumulando un debito tecnico paralizzante che tornerà a perseguitarti quando qualcuno se ne andrà e un nuovo assunto dovrà entrare e accelerare.

Sì, potrebbe essere costato altre 2-3 ore per scrivere i test unitari, ma se il codice viene rispedito dai test, dovrai testare di nuovo manualmente tutto e documentare di nuovo i tuoi test - non lo fai? Altrimenti come fa a sapere cosa hai testato e quali valori hai usato?

I test unitari documentano il comportamento previsto del codice utilizzato dai dati del test per verificarne la funzionalità e danno ai nuovi programmatori la ragionevole sicurezza di non aver rotto qualcosa durante le modifiche.

Oggi costa un paio d'ore in più rispetto ai test manuali, ma poi si esegue il test ogni volta che si apportano modifiche per risparmiare ore durante la durata del codice.

Tuttavia, se sai che il codice verrà ritirato tra un paio d'anni, tutto ciò che ho detto cambia perché non finirai di inserire i test nel codice e non rimborserà mai.


"e documentare di nuovo i test - non lo fai?" - {indossare il cinico cappello:} Certo che no. Non siamo nella terra delle fate degli sviluppatori. Le cose vengono implementate, testate e spedite. Successivamente viene rotto, riparato, testato e spedito.
Martin Ba,

Spero che tutto venga testato manualmente indipendentemente dal numero di test unitari. I test di accettazione automatizzati sono completamente un'altra questione. Ma poi i test di accettazione non sono resi più difficili dal fatto che la base di codice è legacy, quindi qui non rientrano nell'ambito.
pdr,

2
mcottle - Ti manca un punto vitale . Il test dell'unità non diminuirà il tempo impiegato per eseguire il "test di funzionalità manuale" della funzione finita. Devo ancora fare clic su tutte le finestre di dialogo coinvolte con un sottoinsieme prudente di possibili input per assicurarmi che l'app finita effettiva come costruita faccia quello che dovrebbe fare. (Concedo che teoricamente i test unitari potrebbero aiutare a limitare questo ciclo di test manuale a un solo ciclo se i test unitari assicurano che non troverò alcun problema evidente solo durante i test manuali.)
Martin Ba

0

Il valore dei test unitari non sta solo nel testare una nuova funzionalità quando questa viene sviluppata. Il vantaggio dei test unitari si ottiene principalmente in futuro.

Sì, potrebbe essere necessario spendere quello che sembra come una quantità eccessiva di tempo per rendere il codice legacy verificabile.

Ma se non lo fai, dovresti, o sicuramente dovresti , passare molte, molte, molte più ore a testare la funzione. Non solo sul suo sviluppo iniziale, ma con ogni nuova versione del tuo software. Senza test unitari e altre forme di test automatizzati, non si ha altra opzione se non quella di trascorrere molte ore di test manuali per assicurarsi che la funzionalità non sia stata inavvertitamente interrotta, anche quando tale funzionalità stessa non è stata modificata.


1
"Senza test unitari non hai altri mezzi per assicurarti che la tua funzione non sia stata inavvertitamente interrotta, anche quando quella funzione stessa non è stata modificata." - I test unitari non aiuteranno. Per essere veramente sicuro , dovrei avere test di integrazione / accettazione automatizzati.
Martin Ba,

Sì, i test unitari sono solo il primo passo. Risposta modificata per chiarire
Marjan Venema,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.