← Back to Blog

Gli unit test come salvaguardia contro le modifiche involontarie

Gli unit test come salvaguardia contro le modifiche involontarie

Ci aspettiamo che gli unit test verifichino la correttezza della logica modificata e aiutino a individuare cambiamenti involontari nel comportamento dell'applicazione. Nello sviluppo con l'AI è inoltre essenziale controllare che le funzionalità al di fuori dell'ambito del task restino intatte.

Verificare che una nuova funzionalità funzioni è quindi solo una parte del lavoro. Dobbiamo anche controllare che la modifica non abbia rotto le regole esistenti dell'applicazione.

Che cosa dovrebbero proteggere gli unit test

Gli unit test verificano il comportamento delle singole parti del codice. Fungono anche da protezione contro le regressioni, cioè i bug introdotti modificando un comportamento che prima funzionava.

Questa protezione è particolarmente preziosa per il codice generato dall'AI. L'AI può soddisfare un requisito specifico e allo stesso tempo modificare una logica che doveva restare intatta.

Test ben progettati aiutano a definire i confini di una modifica:

Questo è il comportamento che vogliamo cambiare. Queste regole devono continuare a valere.

Testare in base al rischio e alle dipendenze reali

Non dobbiamo scrivere automaticamente un test separato per ogni getter, setter o semplice classe di dati.

Un test che si limita a ripetere l'implementazione può far crescere il numero di test senza aggiungere molto valore. Crea inoltre più lavoro di manutenzione a ogni modifica successiva.

Una regola pratica è:

Per una modifica specifica, concentrati sul comportamento modificato e sulle parti dell'applicazione che ne dipendono. Determina l'ampiezza dei test in base all'impatto potenziale.

Per i metodi semplici senza logica decisionale, un unit test separato può essere superfluo se altri test ne coprono adeguatamente il comportamento.

Tuttavia la semplicità da sola non è un motivo per ritenere che l'AI non sbaglierà. Anche un metodo di una sola riga può determinare il prezzo di un ordine o i diritti di accesso di un utente.

Prima di aggiungere un test, poniti tre domande:

  1. Quale comportamento cambia in questo task?

Verifichiamo che la modifica soddisfi i requisiti.

  1. Quali regole e componenti dipendenti devono restare intatti?

Cerchiamo i punti in cui la modifica potrebbe causare una regressione.

  1. Il test intercetterà un bug reale?

Verifichiamo il comportamento atteso anziché limitarci a copiare l'implementazione.

I test devono collegarsi alla business logic

Gli unit test più preziosi proteggono regole specifiche dell'applicazione.

Per un metodo di calcolo dello sconto, ad esempio, non basta controllare che restituisca un numero. Dobbiamo sapere se queste regole continuano a valere:

  • lo sconto non supera il limite consentito;

  • il prezzo finale non scende sotto zero;

  • un cliente che non ha diritto allo sconto paga il prezzo pieno;

  • il calcolo segue le regole di arrotondamento definite.

Il collegamento tra un metodo e una regola di business è ciò che dà uno scopo a un test.

L'implementazione può cambiare. Una regola al di fuori dell'ambito previsto del task deve rimanere intatta.

Come AITM affronta il tema

AITM collega lo sviluppo con l'AI al contesto del progetto, ai contratti e alle dipendenze tra le diverse parti dell'applicazione.

Prima dell'implementazione, l'architect individua cosa deve cambiare, come sono collegate le parti rilevanti e quali regole devono restare intatte. Lo step di testing usa poi queste informazioni.

La domanda chiave non è quindi solo se l'AI sappia scrivere un test, ma se sappia cosa il test deve proteggere e perché.

Consideriamo una modifica a DiscountService.calculateDiscount(). Se il contratto usa dependsOnModules per registrare che anche OrderSummary.render() dipende dal calcolo dello sconto, lo step di testing ha un motivo per verificare anche l'impatto sul riepilogo dell'ordine.

Il calcolo in sé può essere verificato con un unit test. Un test di integrazione può essere più adatto per verificare come il calcolo lavora insieme al riepilogo dell'ordine.

I test vengono quindi progettati in base alle dipendenze e ai rischi effettivi della specifica modifica.

Dieci test per un task, duemila per un altro

Non tutti i task richiedono la stessa ampiezza di test.

A titolo illustrativo, in un progetto con 32.467 test, una piccola modifica può richiedere l'esecuzione di dieci test rilevanti. Una modifica alla business logic condivisa può richiederne duemila.

Lo scopo dei test mirati è selezionare i test che coprono il comportamento modificato e le sue dipendenze. Questo può accorciare il ciclo di feedback e concentrare la verifica sui rischi del task.

I controlli di regressione più ampi o l'intera suite di test hanno comunque il loro posto per modifiche estese o prima di una nuova release.

Il numero di test eseguiti dovrebbe riflettere l'impatto della modifica.

Quando un test fallisce, dobbiamo capire perché

Un test che fallisce non indica sempre lo stesso problema. Dobbiamo distinguere tra queste situazioni:

  • è stato introdotto un bug nell'implementazione;

  • la modifica ha violato involontariamente una regola di business esistente;

  • una nuova funzionalità ha cambiato intenzionalmente il comportamento atteso e il test va aggiornato.

I requisiti del task, i contratti e le descrizioni della business logic forniscono il contesto per questa valutazione.

Se un requisito è cambiato legittimamente, deve cambiare anche il test corrispondente. Se l'AI ha violato una regola che doveva restare intatta, va corretta l'implementazione.

Modificare semplicemente un test perché torni a passare potrebbe nascondere un bug reale.

Gli unit test sono il primo livello di protezione

Ogni livello di test ha un ruolo diverso:

  • Gli unit test verificano le singole parti della logica.

  • I test di integrazione verificano come lavorano insieme moduli e sistemi.

  • I test E2E controllano percorsi utente completi in un'applicazione in esecuzione.

Questi livelli si completano a vicenda. Ciascuno individua tipi diversi di bug e aiuta a verificare una modifica da una prospettiva diversa.

Nello sviluppo con l'AI controlliamo quindi due cose: se il task è stato completato e se il comportamento al di fuori del suo ambito previsto è rimasto intatto.

Collegare requisiti del task, business logic, dipendenze e test è una parte importante dell'orchestrazione di AITM.

Gli unit test come salvaguardia contro le modifiche involontarie — screenshot 1

Es. unit test

Scopri di più su https://www.aitm.cz

#AITM #UnitTesting #SoftwareTesting #AI #SoftwareDevelopment