Ringraziamo il cielo per i test di regressione. Ero lì, all'inizio di questa settimana, e mi sentivo davvero bene per un nuovo codice che avevo scritto e (pensavo) debuggato. Sto migliorando le funzioni di OpenVOS POSIX che convertono i valori del tempo binario nella struttura temporale scomposta ("struct tm" per voi esperti di C). Nel 1998, quando ho modificato queste routine per farle funzionare in ambiente POSIX, ho preso una scorciatoia e ho chiamato le sottostanti subroutine del kernel VOS. Questo approccio era veloce e semplice ma significava che i nostri runtime POSIX non potevano gestire le date tra il 1970 e il 1980, perché VOS non gestisce quelle date. Ultimamente, ho fatto il porting di diversi nuovi importanti pacchetti open-source su OpenVOS 17.0. Ho scoperto che stavamo fallendo una serie di test perché non riuscivamo a gestire questa gamma di date. Così ho deciso di modificare il codice per gestire tutte le date sia in VOS che in UNIX Epochs (dal 1970 al 2048). Sapevo che questo compito sarebbe stato soggetto a errori, ed ero determinato a trovare un modo per eliminare tutti i bug dal codice. Una delle cose belle del lavoro con le date è che il set è finito. Inoltre, dato che i computer moderni sono abbastanza veloci, non è poi così difficile farli sgranocchiare in tutte le combinazioni possibili e vedere cosa succede. Volevo essere sicuro di testare l'area del codice che ha trattato il 1970 e il 1971, per ragioni che non voglio approfondire qui. Così ho scritto un test che si è convertito 2 volte al giorno, a partire dal 1° gennaio 1970 e fino ad oggi. Ha usato solo una frazione di secondo del tempo della CPU. Certo, ho trovato un errore di fencepost nel mio codice. Ho corretto l'errore e poi il test è passato. Mi sentivo abbastanza bene riguardo a questo procedimento, e i miei auditor hanno approvato le modifiche, e ho pensato di aver finito. Poi, un mio collega ha eseguito la suite di test di regressione sui miei cambiamenti. Lo facciamo dopo ogni modifica ai compilatori e ai loro tempi di esecuzione, giusto per essere sicuri di non rompere accidentalmente qualcosa. Sfortunatamente per me, molti dei test di regressione non sono riusciti. Quando ho scoperto il motivo per cui il mio test non l'aveva preso, nonostante l'apparente accuratezza del test, ho scoperto che i problemi non si sono presentati fino al 2038. Mentre avevo aggiunto il decennio dal 1970 al 1980 alle routine temporali, avevo tagliato il decennio dal 2038 al 2048. Sicuramente, quando sono tornato indietro e ho provato ogni giorno nel range, ho dimostrato che il mio test avrebbe colto il problema, se solo glielo avessi chiesto.
Qual è la lezione qui? Suppongo che la più ovvia sia che se si possono testare tutte le combinazioni, allora si deve essere sicuri di testare tutte le combinazioni. Forse una lezione più importante è quella di prendersi il tempo necessario per costruire una suite di test di regressione. Valgono il tempo e lo sforzo. Possono ridurre i costi e accorciare il tempo per trovare e risolvere i problemi man mano che si migliora il codice. Non è necessario evitare molti problemi segnalati dai clienti per giustificare il costo della creazione di una suite di test di regressione. Stimo che il costo della correzione di un problema software aumenta di un ordine di grandezza ad ogni fase aggiuntiva del processo. Dato che ci sono almeno 4 fasi in ogni processo (progettazione, codice, test, implementazione), le cose diventano costose abbastanza rapidamente.