Da anni mi occupo di software gestionale: in questo ambito la correttezza dell’algoritmo implementato rappresenta la parte più importante del software prodotto.
Quello che voglio dire è che in questo campo specifico elementi come perfomance, bellezza delle UI e architettura impiegata rappresentano fattori assolutamente secondari e trascurabili rispetto alla correttezza e precisione dei risultati prodotti.
Una maschera che permette inserire dei dati contabili può essere bella e funzionale quanto si vuole, nonché essere velocissima e appoggiarsi sull'architettura più estensibile e moderna possibile, ma se capita che in un aggiornamento porti alla situazione in cui un qualsivoglia conteggio previsto dalla faragginosa contabilità italiana risulti essere errato, o anche solo non correttamente arrotondato, allora l’intero software viene considerato una emerita schifezza.
Per questo motivo la gestione dei test del software gestionale prodotto è una procedura che deve sempre essere eseguita con "religiosa" cura: uno sbaglio, seppur minimo, dei calcoli eseguiti è considerato alla stregua di un tradimento.
Nella pratica per realizzare test per tale tipo di software ci si è sempre basati su un approccio misto: parte dei test vengono eseguiti in modo automatico, tramite unit-test, e parte in modo manuale, con l’utilizzo di personale addestrato a trovare, calcolatrice alla mano, i seppur minimi difetti dei calcoli proposti.
Qui parlerò di quanto ho imparato in questi anni circa gli unit test, e vi darò circa gli stessi una mia visione assolutamente personale sia nel loro utilizzo che nella loro implementazione.
So perfettamente che una buona parte di quelli che leggeranno queste righe conoscerà l’argomento anche molto meglio di me: questa serie di post non è infatti stata scritta per Voi, ma per chi ancora cocciutamente non voglia approcciare questo metodo di sviluppo.
Introduzione
Permettetemi un paragone vecchio e ritrito, ma che a mio gusto continua ad essere funzionale ed efficace.
La produzione di software è un processo assimilabile a quello di scrivere un’enciclopedia cartacea (...per chi ancora si ricorda cosa sono le enciclopedie – per chi non lo sapesse consultare la linkografia).
I contenuti di un’enciclopedia sono il risultato di anni di lavoro e attenta revisione, e sono sicuramente precisi e controllati: quindi quando se ne acquista una copia si ottiene un insieme di volumi i cui contenuti sono assolutamente perfetti, o almeno lo sono con buona approssimazione.
Dopo poco, però, alcuni contenuti iniziano a essere obsoleti: vuoi che molti fatti proposti hanno bisogno di aggiornamento, che molti paesi variano assetto e geografia, o anche nuove scoperte scientifiche abbisognano di essere proposte tra i contenuti dell’enciclopedia.
Analogamente non esiste un software che, una volta acquisito, non avrà necessità, dopo un certo periodo di tempo, di una sua revisione.
Il software una volta acquistato di solito, si spera, ha un buon livello di affidabilità: tutte le sue parti sono perfettamente funzionanti e adeguate alle esigenze dell’utilizzatore (...o almeno così dovrebbe essere), proprio come nel caso dell’enciclopedia.
Però con il passare del tempo molte componenti abbisognano di aggiornamento. Vuoi che nel campo di utilizzo intervengono alcune variazioni legislative (vedi per esempio GDPR, che hanno obbligato i produttori di software in qualche modo a incrementare la sicurezza e resilienza del dato trattato nonché la possibilità di cancellarlo per il diritto all’oblio) o anche perché il sistema operativo ospitante propone nuovi modelli di funzionamento o sicurezza: i motivi possono essere molteplici ma esistono sempre.
Per cui un software, similmente ai contenuti di un’enciclopedia, deve sempre essere visto non come un sistema stabile e statico, ma più come un ecosistema vivo che abbisogna di continue modifiche e aggiornamenti.
Ovviamente a quanto sopra possono essere fatte mille osservazioni: in alcuni ambiti il software è meno dinamico che in altri, ma è possibile affermare che che non esiste software non soggetto a necessità di aggiornamenti.
Ecco che però qui il metodo con cui l’enciclopedia e il software vengono aggiornati divergono tra loro, e mostrano ognuno i limiti dell’altro.
Non essendo sensato proporre l’acquisto di una nuova intera enciclopedia aggiornata ogni anno, da sostituire alla vecchia e con le voci aggiornate, le case editrici rilasciano un volume con cadenza periodica (di solito annuale) che propone modifiche e integrazioni alle voci esistenti.
Occorre infatti valutare che solitamente solo un piccolo sottoinsieme di voci presenti è stato aggiornato o aggiunto: il resto continua a essere perfettamente funzionale agli scopi.
Nel software, invece, le cose vanno un po' diversamente: in generale è molto complicato aggiungere nuove funzionalità, o modificare quelle esistenti per integrarle o sistemare bug, senza però intaccare altre funzionalità o parti che nulla hanno a che fare con quelle modificate o integrate.
Più in dettaglio nel caso di un’enciclopedia il volume di aggiornamento rilasciato è supplettivo, e quindi essendo in aggiunta ai volumi esistenti e il contenuti di questi ultimi non viene in alcun modo modificato o variato: nel caso del software le cose sono molto più complicate poiché una modifica di una parte del codice può inficiare il buon funzionamento di altre parti delle stesso.
Per esempio le modifiche eseguite per permettere al nostro software di eseguire dei nuovi calcoli su documenti fiscali potrebbe inficiare regolare funzionamento della stampa degli stessi documenti.
Osservo che in generale quanto esposto sopra è l’eventualità più odiata dagli utilizzatori medi: una funzionalità della app che ha sempre funzionato correttamente e successivamente a un aggiornamento smette di andare come ci aspetta è considerato segno di grande sciatteria.
Quindi occorre un approccio allo sviluppo del software che permetta di eseguire le modifiche enciclopedia-style: le modifiche eseguite in alcun modo devono inficiare la correttezza degli algoritmi esistenti.
Aggiungo un’ulteriore nota, che è egualmente importante: spesso nel campo dei software di gestione aziendale esistono delle “zone d’ombra”, dove alcuni calcoli e cifre proposte non sono perfettamente normate dalla legislazione vigente.
Pertanto i progettisti danno a queste parti un algoritmo preciso, che magari seguono best-practice, al quale gli utilizzatori spesso si abituano.
Variare anche questi tipi di algoritmo è per molti utilizzatori un grosso problema: abituati a certi funzionamenti del software qualsiasi variazione in queste parti è anch’esso fonte di preoccupazione e imprecisione.
Per tutto quanto esposto sopra ci vengono in aiuto gli unit-test: si tratta di test automatici che permettono di eseguire tutta una serie di prove in modo tale da scongiurare quanto esposto sopra.
CI & CD & CD
L’utilità di approntare e utilizzare gli unit test è anche dovuta all’adozione, in questi ultimi anni, di un sistema di rilascio del software basato su CI continuous integration, CD continuous delivery e CD continuous Deployment.
Usando questo approccio in buona sostanza il processo produttivo del software dovrebbe essere volto a rilasciare in produzione agli utilizzatori le nuove revisioni del software con cadenza molto ravvicinate (settimanali o anche giornaliere): ogni nuova release dovrebbe introdurre piccole modifiche agli algoritmi esistenti.
In poche parole qualcosa tipo: rilascio in produzione di modifiche molto piccole & molto frequenti.
Purtroppo la pratica dice che anche a modifiche molto piccole possono corrispondere grandissimi disastri.
Pertanto sopratutto nel caso in cui si adotti una tipologia di rilasci di questo genere gli unit-test diventano indispensabili.
Evidenzio che per software gestionali complessi realizzare un test completo di funzionalità con operatori umani impegna anche svariati giorni-uomo, mentre con gli unit-test se ben programmati in pochi minuti si è in grado di avere un buon grado di sicurezza che almeno le funzionalità principali degli algoritmi implementati sono corretti.
Linkografia