Salvatore Sanfilippo sostiene che il software si stia muovendo verso test agentici, dove LLM imitano utenti e QA per scoprire bug prima del rilascio. Nel farlo, legge la riscrittura di Banne in Rust come un caso che mostra i limiti dei test tradizionali e delle codebase cresciute con l’AI.
Quando il responsabile di un progetto dice che la riscrittura è finita perché “il 100% dei test passano”, Sanfilippo sente suonare un allarme. Per lui quella frase descrive un’idea seducente ma fragile del software, come se una suite fissa potesse garantire la copertura di tutti gli stati possibili. La sua tesi è che quel modello stia perdendo centralità, e che al suo posto stia emergendo un modo più sporco, più costoso e più realistico di verificare i programmi: farli attraversare da agenti che si comportano come utenti, QA engineer e perfino sviluppatori virtuali. La promessa non è l’infallibilità, ma una probabilità più alta di scoprire i guai prima che arrivino agli utenti.
Sanfilippo parte da una reazione quasi istintiva alla riscrittura di Banne: l’idea che una codebase sia davvero corretta perché “il 100% dei test passano” gli sembra rassicurante solo in superficie. La sua obiezione è netta: non sta parlando di copertura delle righe, già difficile in un progetto grande, ma di copertura degli stati, cioè della parte davvero decisiva del comportamento di un sistema.
Abbiamo finito la riscrittura ed è completa perché ora il 100% dei test passano.
Sto parlando del 100% di copertura degli stati. Quindi, praticamente, è come dire: bene, ora funziona come l’altro, ma come fai a sapere che ciò sia vero? È sostanzialmente impossibile.
Da qui il punto più ampio: il testing tradizionale, per Sanfilippo, è già pieno di buchi e vive grazie a pratiche extra che non rientrano nei test automatici classici. Proprio perché i test non bastano, nei progetti grandi esistono team di QA che fanno integrazione, smoke test e prove più vicine al comportamento reale del software.
Se i test fossero così come nel modello mentale, non ci sarebbe bisogno dei team di QA di fare test di integrazione di questo tipo.
Noi sappiamo che è completamente pieno di buchi la nostra metodologia di testing che adottiamo.
La soluzione che Sanfilippo immagina è un passaggio dal test fisso al test agentico*. Invece di lanciare sempre gli stessi controlli, si descrive in un file markdown un compito, e un LLM viene messo a fare da QA engineer, chiamando tool, colpendo endpoint API, inventando sequenze d’uso e cercando di rompere il sistema come farebbe una persona reale.
Faccio un file testing.md, un file markdown in cui gli dici: in questo testo proverai questo prodotto, sarai un QA engineer e farai delle sessioni di prova con tool calling.
È come se tu stessi esponendo il tuo sistema agli utenti prima che gli utenti lo vedano.
Sanfilippo porta un esempio da Redis per gli array: invece di scrivere pochi casi chiusi, lasciava che il prompt chiedesse all’LLM di inventare use case, stressare gli array con programmi Python e scalare i carichi da 10 a 100.000, da 1 milione a 50 milioni di entry. Poi aggiungeva replicazione, coerenza tra repliche, salvataggio e ricarico, cioè una sequenza che assomiglia più a una prova da laboratorio che a un unit test.
Devi inventarti degli use case, scrivere dei programmi Python che stressano gli array per quello use case e poi iniziare a scalarlo sempre di più.
Poi ti metti in mezzo alla replicazione, vedi se i dati sono perfettamente coerenti tra le due repliche, poi salvi, ricarichi.
Il vantaggio del metodo, per Sanfilippo, è che non cerca una verità astratta ma una probabilità più alta di intercettare il difetto prima del rilascio. Il test non è identico ogni volta, perché l’LLM campiona in modo diverso e il sistema stesso introduce indeterminazione, specie quando ci sono timing, chiamate di tool e parsing di output da parte di agenti di coding.
Questo test non è sempre diverso perché l’LLM già fa sampling quando genera, quindi cambia.
Probabilmente lo becchi prima, anche perché questa roba la puoi fare girare anche volendo di continuo.
Per questo Sanfilippo descrive un secondo agente che verifica se il bug è reale, in modo da filtrare i falsi positivi e aprire, se serve, una mail o una issue automatica. Il risultato è un flusso che assomiglia a una piccola fabbrica di QA, con LLM che testano, altri LLM che confermano, e il team umano che riceve solo gli allarmi più solidi.
Puoi eseguire dei test in cui continuamente degli LLM testano il tuo sistema. Poi c’è un’altra sessione del modello che verifica se il bug c’è davvero.
Se c’è davvero ti arriva una email, ti si apre una issue automatica, quel che volete.
La seconda metà del ragionamento si sposta sulla riscrittura di Banne in Rust*. Sanfilippo dice che il passaggio farà emergere “un sacco di magagne” non ancora viste, e lega questa previsione alla storia del software: ogni riscrittura promette pulizia, ma spesso porta con sé nuova complessità e nuovi problemi da scoprire strada facendo.
La riscrittura di Banne in Rust, come tutte le riscritture, farà emergere che ci sono un sacco di magagne di cui ancora non si sono accorti.
Questo fa parte proprio della storia del software.
Qui Sanfilippo corregge anche una lettura che, a suo dire, ha circolato male nei commenti: l’aumento da 600.000 a 1 milione di linee di codice non sarebbe imputabile solo a Rust, perché anche il codice precedente era stato scritto con l’aiuto dell’AI. Il suo punto non è difendere una tecnologia contro l’altra, ma rifiutare un’analisi che confonde la lingua del codice con la qualità del prodotto finale.
Se usate come argomento il fatto che ora il codice Rust fa schifo, sappiate che vi siete persi che anche quello di prima era scritto con le AI.
Secondo lui, le riscritture in Rust tendono a diventare più verbose anche per un altro motivo: gli LLM, nel tentativo di gestire la complessità del linguaggio, aggiungono layer di estrazione e passaggi intermedi che un umano esperto forse eviterebbe. Da qui la sua critica più generale, che non riguarda solo un linguaggio ma il rischio di finire in un minimo locale da cui è difficile uscire senza rifare quasi tutto da capo.
Le riscritture in Rust finiscono per essere leggermente più verbose per una quantità di motivi, però specialmente perché gli LLM cercano di contrastare certe complessità di Rust con più layer di estrazione.
Sanfilippo chiude con una tesi da ingegnere pratico: quando si decide una direzione, conviene investire molto tempo all’inizio per scegliere la cosa giusta e farla crescere in modo organico, invece di usare i test passanti come prova sufficiente che il lavoro sia buono. Il suo bersaglio non è la riscrittura in sé, ma la tentazione di confondere un segnale operativo con una garanzia sostanziale.
Conviene investire molto tempo all’inizio per beccare la cosa giusta e poi fare crescere quella cosa giusta in maniera organica.
Non è che per quando non ne vediamo gli sforzi non ci sono. Quegli sforzi ci sono, noi non li vediamo.
Per Sanfilippo, la prova più concreta che il codice sia debole non è un manifesto teorico, ma la sua farroginosità, la lentezza nel modificarlo, la fatica che il team incontra quando prova a cambiarlo. In questo senso il test agentico non sostituisce il giudizio umano, ma cerca di anticiparlo, mettendo il software davanti a un pubblico artificiale prima che arrivi quello vero.
Che cos’è il test agentico secondo Sanfilippo?
È un test in cui un LLM simula un QA engineer o un utente, prova il prodotto, usa tool e cerca di rompere il sistema. Sanfilippo lo vede come una parte sempre più grande del testing futuro.
Perché il 100% dei test non basta?
Perché, secondo Sanfilippo, non copre davvero tutti gli stati possibili di un software complesso. I test verdi danno fiducia, ma non provano che il sistema si comporti bene in ogni situazione reale.
Perché parla di Rust in questa discussione?
Perché usa la riscrittura di Banne in Rust come esempio dei limiti delle riscritture e dei test tradizionali. Secondo lui, una riscrittura fa emergere bug e spesso produce codice più verbose.
Gli LLM possono sostituire il QA umano?
No, non secondo Sanfilippo. Possono però imitare molte attività di QA e trovare problemi prima, mentre l’umano resta necessario per giudicare i casi ambigui e i falsi positivi.
Qual è la sua critica ai commenti sulla riscrittura?
Che molti hanno attribuito a Rust l’aumento di codice, ignorando che anche la versione precedente era stata scritta con AI. Per lui la discussione è stata confusa sia nei fatti sia nella logica.
Sintesi assistita dall'AI del podcast di Salvatore Sanfilippo, verificata sulla trascrizione originale.