Fortunatamente per te, dal momento che la funzione non sta facendo molto, sarebbe facile anche testarla. Alcuni secondi che utilizzerai per aggiungere un test unitario valgono una potenziale perdita di pochi minuti se qualcuno modifica inavvertitamente la funzione, o se la funzione si interrompe, influenzata da una modifica da qualche altra parte.
Come potrebbe una funzione così semplice interrompere?
Un esempio di regressione
Facciamo un esempio di un linguaggio tipizzato in modo dinamico. Sei nel mezzo di un refactoring per le ultime due settimane; alcune chiamate sono già state migrate a newFunc
e solo pochissime sono ancora basate su oldFunc
. Il nuovo codice è ben testato, ma oldFunc
non ha affatto test.
Il tuo collega inizia a controllare un bug report. Sembra che sia correlato a un pezzo di codice ristretto in cui, tra gli altri, viene chiamato newFunc
. Per correggere il bug, il tuo collega decide di aggiungere un argomento a newFunc
: ora è newFunc(args, isSomething)
e può essere chiamato specificando True
o False
per isSomething
.
Il tuo collega esegue test unitari e, uno per uno, li corregge aggiungendo il parametro mancante ai chiamanti. La suite di test ora è completamente verde, quindi invia le modifiche alla produzione.
Alcuni minuti dopo, il telefono inizia a squillare ...
Poiché ti sei dimenticato di testare oldFunc
, la modifica non è stata presa dalla suite di test. Il tuo collega ha introdotto una regressione perché il codice non è stato verificato . Semplicemente guardando il codice, il tuo collega non aveva idea di dover aggiornare oldFunc
e tutti i chiamanti di oldFunc
.
Che cosa testare?
Come puoi immaginare, non è necessario scrivere tutti i test unitari di newFunc
per oldFunc
: i test di oldFunc
dovrebbero testare solo cosa sta facendo la funzione effettiva, non cosa qualche altra funzione chiamata è in esecuzione.
Questo significa che dovresti limitarti a un eventuale test.
Ulteriori modifiche
Se la vecchia funzione viene mantenuta solo temporaneamente, puoi - se la lingua ha un supporto per essa - decorare la funzione come obsoleta per fare in modo che il compilatore produca una serie di avvertimenti per ogni posizione nel codice che utilizza ancora la vecchia funzione . Il passo successivo potrebbe essere quello di sostituire la chiamata alla nuova funzione con un'eccezione, per catturare alcune posizioni in cui la funzione è stata chiamata, senza essere catturata dal compilatore; il test verrà quindi modificato di conseguenza per verificare che l'eccezione sia stata lanciata.