Salta al contenuto principale

Glossario

Test di Accettazione

Un test di accettazione verifica che una funzionalità soddisfi un requisito di business dal punto di vista dell'utente, espresso in termini di comportamento osservabile anziché di implementazione interna. È spesso scritto in forma Given/When/Then ed eseguito contro un sistema completo o realmente integrato. Risponde alla domanda "abbiamo costruito la cosa giusta?" piuttosto che "abbiamo costruito la cosa nel modo giusto?".

Arrange-Act-Assert (AAA)

Arrange-Act-Assert è una convenzione strutturale per il corpo di un test: predisporre gli input e le precondizioni (arrange), eseguire l'unità sotto test una sola volta (act) e verificare l'esito atteso (assert). Mantenere le tre fasi visivamente distinte rende il test leggibile e segnala quando fa troppe cose (più passi di act). È la versione procedurale del Given/When/Then usato nel BDD.

Asserzione

Un'asserzione è un'istruzione in un test che dichiara una condizione attesa; se la condizione è falsa il test fallisce. Buone asserzioni sono specifiche e producono un messaggio di fallimento chiaro che indica i valori atteso e effettivo. Un test dovrebbe in genere verificare un solo comportamento logico, anche se ciò richiede più chiamate di assert che descrivono lo stesso esito.

Black-Box Testing

Il black-box testing esercita un sistema attraverso la sua interfaccia pubblica senza conoscere la struttura interna, derivando i casi dalla specifica, dagli input e dagli output. È complementare al white-box testing, che usa la conoscenza del codice per colpire percorsi e rami. Il partizionamento di equivalenza e l'analisi dei valori limite sono tecniche black-box classiche.

Analisi dei Valori Limite

L'analisi dei valori limite è una tecnica di progettazione dei test che concentra i casi sui bordi degli intervalli di input, dove i difetti si addensano, anziché sui valori interni tipici. Per un intervallo valido da 1 a 100 testa 0, 1, 2, 99, 100 e 101. Si abbina naturalmente al partizionamento di equivalenza, che prima raggruppa gli input che dovrebbero comportarsi in modo identico.

Code Coverage

Il code coverage misura la quota di codice di produzione eseguita da una suite di test, riportata come copertura di righe, rami, istruzioni o condizioni. È un indicatore di completezza, non una misura della qualità dei test: il 100% di copertura delle righe può comunque tralasciare comportamenti e percorsi di errore. Va trattato come strumento per individuare codice non testato, non come obiettivo da aggirare.

Contract Test

Un contract test verifica che un servizio rispetti il contratto di richiesta/risposta su cui un consumatore fa affidamento, così che il fornitore possa evolvere in sicurezza. Nel consumer-driven contract testing il consumatore pubblica le proprie aspettative (un pact) e il fornitore verifica di poterle soddisfare in isolamento. I contract test colgono le rotture di integrazione senza il costo e la fragilità degli ambienti end-to-end completi.

Complessità Ciclomatica

La complessità ciclomatica conta il numero di percorsi linearmente indipendenti attraverso un frammento di codice, all'incirca uno più il numero di punti decisionali. Indica il numero minimo di casi di test necessari per coprire ogni ramo ed è un segnale utile su dove si annidano bug e percorsi non testati. Un'alta complessità è un innesco per il refactoring tanto quanto per il testing.

Difetto (Bug)

Un difetto è un'imperfezione nel codice o nel design che fa comportare il sistema diversamente dalla sua specifica o dalla ragionevole aspettativa dell'utente. Un difetto trovato in produzione è molto più costoso da correggere di uno trovato in sviluppo, ed è questo l'argomento economico per spostare il testing a sinistra. I difetti sono distinti dai guasti (il sintomo osservabile) e dagli errori (lo sbaglio umano che li ha introdotti).

Test End-to-End (E2E)

Un test end-to-end esercita un percorso utente completo attraverso il sistema interamente integrato, tipicamente pilotando la UI reale e i servizi sottostanti come farebbe un utente. I test E2E danno la massima fiducia che il prodotto assemblato funzioni, ma sono i più lenti, fragili e costosi da mantenere, perciò stanno nel vertice stretto della piramide dei test. Vanno tenuti pochi e riservati ai percorsi critici.

Partizionamento di Equivalenza

Il partizionamento di equivalenza divide il dominio degli input in classi che il sistema dovrebbe trattare in modo identico, così che testare un valore rappresentativo per classe approssimi il testarle tutte. Riduce il numero di casi senza sacrificare la copertura significativa ed è di solito combinato con l'analisi dei valori limite ai bordi di ogni partizione. Si applica sia alle classi di input valide sia a quelle non valide.

Testing Esplorativo

Il testing esplorativo è apprendimento, progettazione ed esecuzione dei test simultanei, in cui il tester indaga attivamente il sistema e usa i risultati per orientare l'azione successiva. È strutturato (spesso suddiviso in "sessioni" cronometrate con una carta d'intenti), non casuale, ed eccelle nel trovare difetti che i test scriptati mancano. Completa, anziché sostituire, i controlli di regressione automatici.

Fake

Un fake è un test double con un'implementazione funzionante ma semplificata, come un repository in memoria al posto di un database. A differenza di un mock o di uno stub, un fake fa qualcosa di utile, il che lo rende adatto ai test in stile integrazione dove si vuole comportamento reale senza infrastruttura reale. È uno dei cinque tipi di test double nominati da Gerard Meszaros.

Test Instabile (Flaky)

Un test instabile è quello che passa e fallisce in modo non deterministico sullo stesso codice, erodendo la fiducia nella suite e mascherando regressioni reali. Cause comuni sono condizioni di timing e di race, dipendenza dall'orologio di sistema, stato mutabile condiviso, dipendenza dall'ordine dei test e dipendenze esterne instabili. La soluzione è rendere il test deterministico (controllare il tempo, attendere condizioni e non sleep, isolare lo stato), non ritentarlo alla cieca.

Fixture

Una fixture è lo stato di base e i dati fissi di cui un test ha bisogno prima di essere eseguito, predisposti in anticipo e smantellati dopo. Una buona fixture è minima ed esplicita, così che il lettore veda esattamente da cosa dipende il test. Gli hook di setup/teardown (come @BeforeEach/@AfterEach di JUnit) costruiscono e smontano le fixture attorno a ciascun test.

Fuzz Testing

Il fuzz testing alimenta un programma con grandi volumi di input casuali, malformati o inattesi per far emergere crash, blocchi, errori di memoria ed eccezioni non gestite. I fuzzer guidati dalla copertura (come quelli basati su libFuzzer o sul fuzzing nativo di Go) mutano gli input per massimizzare i percorsi di codice raggiunti. È particolarmente efficace per parser, decoder e qualsiasi codice su un confine di fiducia.

Given-When-Then

Given-When-Then è un modo strutturato di formulare un esempio di comportamento: Given un contesto di partenza, When si verifica un'azione, Then vale un esito atteso. Proviene dal Behaviour-Driven Development e sta alla base degli scenari Gherkin usati da strumenti come Cucumber. Si mappa direttamente sulla struttura Arrange-Act-Assert del corpo di un test.

Golden Test (Snapshot Test)

Un golden o snapshot test confronta l'output corrente con un output di riferimento ("golden") approvato in precedenza, fallendo a ogni differenza. È efficiente per output strutturati di grandi dimensioni (UI renderizzata, dati serializzati) ma può cristallizzare i bug se gli snapshot vengono ri-approvati alla cieca. Va rivisto il diff dello snapshot con la stessa cura del codice, mantenendo gli snapshot piccoli e significativi.

Test di Integrazione

Un test di integrazione verifica che più componenti funzionino correttamente insieme, spesso con infrastruttura reale come un database, un message broker o una dipendenza HTTP. Coglie difetti di cablaggio, mapping, SQL e serializzazione che i test unitari con mock non possono. Strumenti come Testcontainers rendono affidabili i test di integrazione avviando dipendenze reali in container usa-e-getta.

Load Test

Un load test misura come un sistema si comporta sotto un livello atteso o di picco di domanda concorrente, riportando percentili di latenza, throughput e tasso di errore. Risponde a "il sistema rispetta i suoi obiettivi di performance a questo volume?" ed è distinto dallo stress test, che spinge oltre i limiti per trovare il punto di rottura. I load test dovrebbero verificare la latenza di coda (p95/p99), non solo le medie.

Mock

Un mock è un test double pre-programmato con aspettative sulle chiamate che dovrebbe ricevere, e può far fallire il test se quelle aspettative non sono soddisfatte. I mock verificano le interazioni (verifica del comportamento) anziché lo stato finale, il che li rende potenti ma inclini ad accoppiare i test ai dettagli di implementazione. L'eccesso di mock è uno smell comune che produce test che passano su codice rotto.

Mutation Testing

Il mutation testing misura la qualità di una suite di test introducendo piccoli guasti ("mutanti") nel codice e verificando se i test li catturano. Un mutante sopravvissuto rivela un comportamento che i test non verificano davvero, anche se la copertura è alta. Il mutation score (mutanti uccisi sul totale) è un segnale di qualità molto più forte della copertura delle righe, al costo di tempi di esecuzione più lunghi.

Test Negativo

Un test negativo verifica che il sistema gestisca con grazia input non validi, condizioni di errore e usi impropri - rifiutando i dati errati, restituendo l'errore corretto e non corrompendo lo stato. Completa il test positivo del "percorso felice" ed è dove vivono molti difetti reali in produzione. Saltare i casi negativi è una causa frequente di bug fragili e rilevanti per la sicurezza.

Page Object Model (POM)

Il Page Object Model è un pattern di progettazione per i test di UI che incapsula ogni pagina o componente dietro un oggetto che espone metodi rivelatori di intenzione, nascondendo selettori e dettagli di interazione. Localizza i cambiamenti di UI in un solo punto, così che un selettore modificato si corregga una volta sola anziché in ogni test. È il modo standard per mantenere manutenibili le suite Selenium e Playwright.

Property-Based Testing

Il property-based testing afferma che una proprietà vale per molti input generati automaticamente, anziché controllare pochi esempi scelti a mano. Il framework (come Hypothesis, jqwik o fast-check) genera i casi e "restringe" uno fallito a un controesempio minimo. È eccellente per trovare casi limite in funzioni pure, serializzatori e invarianti come "decode(encode(x)) == x".

Quality Assurance (QA)

La quality assurance è l'insieme delle attività orientate al processo che costruiscono la qualità nel modo in cui il software viene prodotto, in contrapposizione al quality control, che ispeziona il prodotto finito alla ricerca di difetti. La QA abbraccia chiarezza dei requisiti, code review, strategia di test e miglioramento continuo. I team moderni trattano la qualità come responsabilità dell'intero team anziché come una fase di un gruppo separato.

Test di Regressione

Un test di regressione protegge dalla reintroduzione di un difetto già corretto o dalla rottura del comportamento esistente da parte di un nuovo cambiamento. Ogni correzione di bug dovrebbe aggiungere un test che fallisce prima della correzione e passa dopo, così che il bug non possa tornare silenziosamente. La suite di regressione che si accumula viene eseguita a ogni cambiamento per evitare che il sistema regredisca.

Smoke Test

Uno smoke test è un piccolo insieme di controlli rapidi che conferma che le funzionalità più critiche di una build funzionino del tutto, eseguito per primo per decidere se un testing più approfondito ha senso. Il nome viene dal test hardware - accendilo e vedi se fa fumo. Nel CI/CD funge da gate rapido dopo il deploy, prima di suite più ampie o dell'ammissione del traffico.

Stub

Uno stub è un test double che restituisce risposte predefinite alle chiamate effettuate durante il test, fornendo gli input indiretti di cui un'unità ha bisogno senza alcuna logica reale. A differenza di un mock, uno stub non verifica come è stato chiamato; fornisce solo stato. Gli stub mantengono semplici i test basati sullo stato e disaccoppiati dal comportamento dei collaboratori.

System Under Test (SUT)

Il system under test è il codice specifico esercitato da un dato test - una singola classe per un test unitario, una fetta di servizi per un test di integrazione, l'intera applicazione per un test E2E. Nominare con precisione il SUT chiarisce l'ambito del test e quali siano i suoi collaboratori (reali o sostituiti). Un confine sfumato del SUT è causa frequente di test lenti, fragili o difficili da interpretare.

Caso di Test

Un caso di test è un singolo scenario ripetibile con precondizioni, input, passi di esecuzione ed esito atteso definiti, usato per determinare se una funzionalità si comporta correttamente. Buoni casi di test sono indipendenti, deterministici e tracciabili a un requisito o comportamento. Una suite è una raccolta curata di casi di test organizzata per funzionalità, rischio o livello.

Test Double

Un test double è qualsiasi oggetto che sostituisce un collaboratore reale durante un test; il termine ombrello copre dummy, stub, fake, spy e mock. Scegliere il double giusto conta: stub e fake supportano la verifica dello stato, mentre mock e spy supportano la verifica delle interazioni. La tassonomia è stata resa popolare da Gerard Meszaros in xUnit Test Patterns.

Piramide dei Test

La piramide dei test è un'euristica per la forma ideale di una suite: molti test unitari veloci alla base, meno test di integrazione nel mezzo e pochissimi test end-to-end lenti in cima. Ottimizza per un feedback rapido e affidabile spingendo il testing verso il livello più economico in grado di cogliere un dato difetto. Invertirla (un "cono gelato" fatto soprattutto di test E2E) produce suite lente e instabili.

Test-Driven Development (TDD)

Il Test-Driven Development è un flusso di lavoro in cui si scrive prima un test che fallisce (red), si scrive il codice minimo per farlo passare (green) e poi si refattorizza con il test come rete di sicurezza (refactor). Guidare il design dai test tende a produrre unità piccole, disaccoppiate e testabili e una suite di regressione come sottoprodotto. La disciplina riguarda design e feedback, non il semplice avere dei test.

Test Fixture

Una test fixture è l'ambiente preparato - oggetti, dati e configurazione - in uno stato noto contro cui uno o più test vengono eseguiti. Le fixture condivise velocizzano le suite ma rischiano accoppiamento nascosto e dipendenza dall'ordine; le fixture per-test sono isolate ma più lente. Il compromesso tra condivisione e isolamento è una decisione centrale di progettazione dei test.

Oracolo di Test

Un oracolo di test è il meccanismo che decide se l'output osservato di un test è corretto. Può essere un valore atteso esatto, una proprietà o un'invariante, un confronto con un'implementazione di riferimento o un giudizio umano. Il "problema dell'oracolo" - conoscere la risposta giusta per sistemi complessi o non deterministici - è una sfida fondamentale del testing, inclusi i sistemi di IA.

Piano di Test

Un piano di test è un documento che descrive l'ambito, l'approccio, le risorse, la pianificazione e le priorità basate sul rischio per uno sforzo di testing. Registra cosa sarà e non sarà testato, gli ambienti e i dati necessari e i criteri di ingresso/uscita di ciascuna fase. Piani di test leggeri e vivi si adattano ai team agili meglio dei documenti pesanti definiti in anticipo.

Suite di Test

Una suite di test è una raccolta nominata di casi di test raggruppati per l'esecuzione - per funzionalità, per livello (unit/integration/E2E) o per cadenza di esecuzione (smoke, notturna, completa). Organizzare le suite consente a una pipeline di eseguire controlli rapidi a ogni commit e controlli più lenti e ampi più di rado. Una suite ben strutturata dà agli sviluppatori feedback alla giusta velocità per ogni fase.

Criteri di Accettazione

I criteri di accettazione sono le condizioni predefinite che una funzionalità deve soddisfare per essere considerata completata e accettata dagli stakeholder. Scritti prima o durante lo sviluppo, rendono oggettivo il "fatto" e diventano la base dei test di accettazione. Criteri chiari e testabili riducono il rilavoro causato da requisiti ambigui.

Spy

Uno spy è un test double che registra informazioni su come è stato chiamato (argomenti, numero e ordine delle chiamate) così che il test possa fare asserzioni su quelle interazioni in seguito. Sta tra uno stub (fornisce risposte) e un mock (verifica aspettative impostate in anticipo): uno spy cattura prima e verifica dopo. Gli spy sono utili quando si vuole una verifica delle interazioni allentata senza scrivere aspettative rigide in anticipo.

Stress Test

Uno stress test spinge deliberatamente un sistema oltre la capacità attesa per trovare il punto di rottura e osservare come degrada e si riprende. A differenza di un load test, che valida il comportamento a un volume obiettivo, uno stress test cerca la modalità di guasto - esaurimento delle risorse, timeout a cascata o corruzione dei dati. L'obiettivo è un degrado graduale e un recupero pulito, non la sopravvivenza a un carico impossibile.

Soak Test

Un soak test (di resistenza) esegue un sistema sotto un carico sostenuto e moderato per un periodo prolungato per rivelare problemi che emergono solo nel tempo, come memory leak, esaurimento del pool di connessioni e lenta erosione delle risorse. Risponde a "il sistema resta sano per ore o giorni?", cosa che i load test brevi non possono. È essenziale prima di promettere un'alta SLO di uptime.

Continuous Integration (CI)

La Continuous Integration è la pratica di integrare il lavoro degli sviluppatori in un tronco condiviso frequentemente, con ogni integrazione verificata da una build e un'esecuzione di test automatici. Una CI veloce e affidabile coglie presto i difetti di integrazione e mantiene il tronco rilasciabile. La strategia di test deve mantenere veloce il feedback della CI, che è la motivazione pratica della piramide dei test.

Shift-Left Testing

Lo shift-left testing sposta le attività di qualità più a sinistra nel ciclo di vita - scrivere i test con il codice, rivedere i requisiti per la testabilità ed eseguire controlli a ogni commit - anziché testare solo alla fine. Poiché i difetti diventano esponenzialmente più costosi quanto più tardi vengono trovati, coglierli presto abbassa costo e lead time. Riconfigura il testing da gate ad attività continua e integrata.

Code Review

La code review è la pratica di far esaminare un cambiamento da uno o più ingegneri prima del merge, concentrandosi su correttezza, sicurezza, design e adeguatezza dei test. È un'attività di quality assurance che coglie difetti e diffonde conoscenza che i test automatici non possono. Le review efficaci sono tempestive, di piccola portata e verificano che i test affermino davvero comportamenti significativi.

Densità dei Difetti

La densità dei difetti è il numero di difetti confermati diviso per una misura di dimensione del componente, come difetti per mille righe di codice o per function point. Aiuta a confrontare la qualità relativa dei moduli e a individuare gli hotspot che meritano più test o refactoring. Come tutte queste metriche, è un segnale da indagare, non un verdetto a sé stante.

Percorso Felice

Il percorso felice è lo scenario di default in cui tutto va come previsto, con input validi e nessun errore. Testare solo il percorso felice è una lacuna comune, perché la maggior parte dei difetti in produzione e dei problemi di sicurezza vive nella gestione degli errori, nei casi limite e negli input inattesi. Una suite bilanciata abbina a ogni test di percorso felice casi negativi e di confine.

Isolamento dei Test

L'isolamento dei test significa che ogni test viene eseguito indipendentemente dagli altri, senza stato mutabile condiviso né assunzioni di ordinamento, così da poter girare da solo, in qualsiasi ordine e in parallelo con lo stesso risultato. L'isolamento è ciò che rende una suite affidabile e parallelizzabile; la sua assenza è una causa principale di fallimenti instabili e dipendenti dall'ordine. Si ottiene reimpostando o ricreando le fixture per test ed evitando lo stato globale.

Suite di Regressione

Una suite di regressione è il corpo accumulato di test automatici eseguiti a ogni cambiamento per confermare che il comportamento esistente funzioni ancora. Cresce man mano che correzioni di bug e funzionalità contribuiscono ciascuna con i propri test di guardia. Il suo valore dipende dal restare veloce e affidabile; test instabili o lenti vengono ignorati o disabilitati, il che rimuove silenziosamente la protezione.