Partizionamento di equivalenza: tecnica di progettazione dei test spiegata con esempi pratici

  1. Home
  2. Blog
  3. Test del software

Test del software

Partizionamento di equivalenza: Tecnica di progettazione dei test spiegata con esempi pratici

Non puoi testare ogni possibile input, quindi quali valori dovresti scegliere? Il partizionamento per equivalenza fornisce una risposta chiara. Impara il metodo passo dopo passo, lavora attraverso esempi reali e scopri dove ha bisogno di aiuto.

8 min di lettura
Tecnica di progettazione dei test di partizionamento di equivalenza spiegata con esempi pratici

Punti chiave

  • Il partizionamento per equivalenza divide gli input in gruppi che dovrebbero comportarsi allo stesso modo.
  • Testare un valore rappresentativo di ciascun gruppo anziché ogni valore.
  • Includere sempre le partizioni non valide, poiché la gestione degli errori è il luogo in cui si nascondono molti bug.
  • Funziona meglio insieme all’analisi dei valori limite, perché i bug spesso si trovano ai margini di un gruppo.

Un campo età che accetta da 18 a 60 anni ha un numero enorme di possibili input, una volta contati i negativi, i numeri enormi, il testo e gli spazi vuoti. Nessuno può provarli tutti. Il partizionamento per equivalenza risolve questo problema, raggruppando gli input che il software dovrebbe trattare allo stesso modo e quindi testando un valore da ciascun gruppo.

È una delle prime tecniche di progettazione dei test che ogni tester dovrebbe apprendere. In questa guida lo analizzeremo passo dopo passo e testeremo un esempio in Python. Abbiamo eseguito quel codice su Python 3.13 e il suo output è incluso. Le regole relative alla password e al coupon riportate di seguito sono esempi illustrativi, non presi da un sistema reale.

Cos’è il partizionamento per equivalenza?

Il partizionamento di equivalenza, chiamato anche partizionamento di classi di equivalenza (ECP), è una tecnica di progettazione di test a scatola nera. Divide i possibili input di una funzionalità in partizioni o classi. Ci si aspetta che ogni valore all’interno di una partizione produca lo stesso tipo di comportamento.

Poiché non è necessario visualizzare il codice, è possibile applicarlo direttamente da un requisito. Per saperne di più su questo stile di test, leggi Test della scatola nera e della scatola bianca.

Perché funziona

La tecnica si basa su un presupposto: se un valore in una partizione trova un bug, probabilmente lo troveranno anche gli altri in quella partizione. E se un valore passa, probabilmente passeranno anche gli altri. Testare 25, 26 e 27 in un campo di età adulta probabilmente non ti dirà nulla che testare 25 da solo non abbia detto.

Avvicinamento Test per un campo età Risultato
Esauriente Ogni valore possibile Impossibile in pratica
Indovinello casuale Qualunque cosa mi venga in mente Duplicati e lacune
Partizionamento per equivalenze Uno per partizione Piccolo, con copertura deliberata

Si tratta però di una supposizione e non di una garanzia. Il software può avere casi speciali nascosti all’interno di una partizione, una limitazione su cui torneremo più avanti.

Come farlo in cinque passaggi

  1. Leggere il requisito e identificare l’input e le sue regole.
  2. Trova le partizioni valide, quali sono i gruppi di valori che dovrebbero essere accettati e nota se intervalli diversi si comportano diversamente.
  3. Trova le partizioni non valide, inclusi valori troppo bassi, troppo alti, tipo sbagliato e vuoti.
  4. Scegli un valore rappresentativo da ciascuna partizione, solitamente da qualche parte nel mezzo.
  5. Annota il risultato atteso per ciascuno, come in qualsiasi buon caso di test.

Esempio realizzato: un campo età

Requisito: Possono registrarsi gli utenti dai 18 ai 60 anni.

Partizione Digitare Valore di prova Risultato atteso
Sotto i 18 Non valido 10 Rifiutato
18-60 Valido 35 Accettato
Sopra i 60 Non valido 75 Rifiutato
Non un numero Non valido “abc” Errore
Vuoto Non valido (empty) Messaggio “richiesto”.

Cinque test ti offrono la copertura di ogni comportamento previsto dal requisito. Molti tutorial si fermano alle prime tre righe, ma le ultime due sono quelle che gli utenti reali attivano per sbaglio. Puoi anche aggiungere righe per numeri negativi o decimali, se questi possono essere ragionevolmente gestiti diversamente.

Testarlo nel codice

Ecco quella regola come funzione, con uno unit test per partizione, usando il built-in di Python unittest:

import unittest

def can_register(age):
    if not isinstance(age, int) or isinstance(age, bool):
        raise TypeError("age must be a whole number")
    return 18 <= age <= 60

class EquivalenceTests(unittest.TestCase):
    def test_valid_partition(self):
        self.assertTrue(can_register(35))

    def test_too_young_partition(self):
        self.assertFalse(can_register(10))

    def test_too_old_partition(self):
        self.assertFalse(can_register(75))

    def test_wrong_type_partition(self):
        with self.assertRaises(TypeError):
            can_register("abc")

La nostra corsa è passata:

test_too_old_partition ... ok
test_too_young_partition ... ok
test_valid_partition ... ok
test_wrong_type_partition ... ok

In un progetto reale, la funzione di parametrizzazione di pytest è un modo accurato per eseguire una tabella di valori di partizione attraverso un singolo test.

Esempio realizzato: una password

Requisito: Una password deve essere lunga da 8 a 20 caratteri e contenere almeno una cifra.

Questo ha due regole, lunghezza e contenuto, quindi consideriamo le partizioni per entrambi:

Partizione Digitare Valore di prova Risultato atteso
Lunghezza valida, contiene una cifra Valido alba42 Accettato
Troppo corto Non valido abc1 Errore: troppo corto
Troppo lungo Non valido Un valore di 30 caratteri con una cifra Errore: troppo lungo
Lunghezza valida, nessuna cifra Non valido Sunriseday Errore: cifra necessaria
Vuoto Non valido (empty) Errore: obbligatorio

Nota che ogni test non valido infrange solo una regola. Se un valore fosse troppo corto e mancasse una cifra, un test superato non potrebbe dirti quale controllo ha funzionato. Un assegno potrebbe essere rotto, mentre l’altro nasconde il fatto.

Esempio realizzato: input non numerici

La tecnica non è limitata agli intervalli di numeri. Anche opzioni, categorie e stati discreti formano partizioni. Supponiamo che un negozio abbia questa regola:

Requisito: La consegna è gratuita per i membri Gold, 50 per i Silver e 100 per tutti gli altri. I valori dei livelli sconosciuti sono errori.

Partizione Valore di prova Commissione prevista
Oro oro 0
Argento argento 50
Nessun abbonamento (none) 100
Livello sconosciuto platino Errore

Qui, ogni opzione ha la propria partizione, poiché ognuna dovrebbe comportarsi in modo diverso. Altre partizioni comuni includono tipi di file, come caricamenti validi e non validi, e gruppi basati sull’output, come un prestito approvato o rifiutato.

Suggerimento: pensa sia agli output che agli input. Se un calcolo può produrre uno sconto, nessuno sconto o un avviso, assicurati che almeno un test raggiunga ciascuno di questi risultati.

Diversi input contemporaneamente

Con più campi, il numero di combinazioni cresce rapidamente. Tre campi con quattro partizioni forniscono ciascuno 64 combinazioni. Due strategie aiutano:

  • Copertura debole: assicurati che ogni partizione appaia in almeno un test, combinando diversi valori validi per test. Per i valori non validi, testarne uno alla volta in modo che gli errori non si nascondano a vicenda.
  • Copertura basata su regole: quando le combinazioni modificano effettivamente il risultato, come lo stato del membro con il valore dell’ordine, utilizza test della tabella decisionale per elencarle correttamente.

Associazione con l’analisi dei valori limite

Il partizionamento indica quali gruppi testare. Dice poco su dove in un gruppo gli insetti amano nascondersi, e molti si nascondono proprio ai bordi. Per dimostrarlo, abbiamo scritto una versione buggy con il classico errore “off-by-one”:

def buggy(age):
    return 18 < age <= 60     # should be 18 <= age

[buggy(a) for a in (35, 10, 75)]   # [True, False, False]
buggy(18)                          # False

I nostri valori di partizione, 35, 10 e 75, hanno dato tutti le risposte corrette, quindi i test sarebbero stati superati. Eppure un 18enne viene ingiustamente rifiutato. Ecco perché le due tecniche vanno di pari passo:

Tecnica Sceglie Valori dai 18 ai 60 anni
Partizionamento per equivalenze Un valore all’interno di ciascun gruppo 10, 35, 75
Analisi del valore limite Valori ai margini di ogni gruppo 17, 18, 60, 61

Utilizzare il partizionamento per trovare i gruppi e quindi i confini per verificare dove si incontrano i gruppi. Nel nostro codice, un test separato per 17, 18, 60 e 61 ha superato la funzione corretta e avrebbe rilevato il bug. La nostra guida all’analisi dei valori limite tratta questo argomento in modo completo.

Vantaggi e limiti

Vantaggi Limitazioni
Riduce notevolmente il numero di test Si basa sulla correttezza delle partizioni
Fornisce una copertura chiara e spiegabile Possono mancare i bug ai confini
Non necessita di accesso al codice Possono mancare casi speciali nascosti
Si applica in anticipo, anche rispetto ai requisiti Non modella bene sequenze o combinazioni

Il rischio più grande è un presupposto errato. Se il codice ha una regola nascosta per un valore specifico, il test scelto potrebbe semplicemente non raggiungerlo. Test esplorativi e copertura del codice ti aiutano a trovare ciò che è mancato alle partizioni.

Errori comuni

  • Dimenticare le partizioni non valide. Testare solo i percorsi felici lascia la gestione degli errori deselezionata.
  • Testare diversi valori da una partizione. Ciò aumenta i costi senza nuove informazioni.
  • Combinazione di diversi valori non validi in un test. Un errore può nasconderne un altro.
  • Saltare i limiti. I soli test delle partizioni spesso non riescono a individuare i bug singoli.
  • Indovinare le regole. Se un requisito non è chiaro, chiedi. Nel 60 dovrebbero rientrare anche le persone che hanno 60 anni e mezzo?

Considerazioni finali

Il partizionamento di equivalenza sostituisce “quanti test dovrei scrivere?” con una domanda molto migliore: “quali comportamenti esistono e li ho trattati ciascuno?” Per provarlo, prendi un modulo che stai testando oggi ed elenca le sue partizioni su carta, comprese quelle non valide. Aggiungi i confini successivamente. Spesso ti ritroverai con meno test che troveranno più bug.

Domande frequenti

Cos’è il partizionamento per equivalenza nei test?

È una tecnica della scatola nera che divide gli input in gruppi che si prevede si comportino allo stesso modo. Quindi testa un valore rappresentativo di ciascun gruppo, non tutti i valori.

Qual è la differenza tra partizionamento di equivalenza e analisi dei valori al contorno?

Il partizionamento seleziona un valore dall’interno di ciascun gruppo. L’analisi del valore limite verifica i valori ai margini di tali gruppi. Di solito vengono usati insieme.

Di quanti casi di test è necessario il partizionamento di equivalenza?

Di solito almeno uno per partizione, sia valido che non valido. Un campo relativo alla fascia di età richiede in genere da tre a cinque test.

Il partizionamento dell’equivalenza è una scatola nera o una scatola bianca?

È una tecnica a scatola nera, poiché le partizioni provengono dai requisiti e non necessitano del codice. Gli sviluppatori possono tuttavia applicarlo anche agli unit test.

Cosa sono le partizioni valide e non valide?

Le partizioni valide contengono valori che il sistema dovrebbe accettare. Le partizioni non valide contengono valori che dovrebbero rifiutare, come numeri fuori intervallo, tipi errati e spazi vuoti.

Continua a imparare

Lavora con Stack Quora

Hai bisogno di aiuto con test, WordPress o SEO?

Aiutiamo i team a fornire software migliore e a far crescere i loro siti. Raccontaci a cosa stai lavorando e ti suggeriremo chiaramente il prossimo passo.

Continua a leggere

Altre guide su test, intelligenza artificiale e sviluppo moderno

Ti è piaciuto questo articolo? Scegli un argomento e passa direttamente ai nostri tutorial più recenti.

Intelligenza artificiale

Spiegazione delle allucinazioni dell'intelligenza artificiale: perché i modelli linguistici inventano le cose e come ridurle

Spiegazione delle allucinazioni dell'intelligenza artificiale: cosa sono, perché i modelli linguistici le producono, tipi comuni, come ridurle con b…

Leggi l'articolo →
DevOps

Spiegazione delle variabili d'ambiente: file .env, segreti e configurazione eseguiti correttamente

Variabili d'ambiente spiegate con esempi Python che abbiamo eseguito: lettura e impostazione, perché ogni valore è una stringa, file .env, ereditari…

Leggi l'articolo →
Sviluppo software

Spiegazione della limitazione della velocità API: algoritmi, intestazioni e gestione degli errori 429

La limitazione della velocità dell'API spiegata con una simulazione che abbiamo eseguito: bucket di token, finestra fissa, finestra scorrevole, risp…

Leggi l'articolo →
Automazione dei test

Derisione in Python: unittest.mock, patch e gli errori che fanno mentire i test

Mocking in Python con unittest.mock, testato: Mock e return_value, side_effect, patch dove viene utilizzato un nome, specifiche e autospec, date moc…

Leggi l'articolo →
Test del software

Spiegazione della copertura del codice: copertura di linea o di filiale e cosa significa realmente il 100%.

Copertura del codice spiegata con una vera esecuzione di cover.py: copertura di linea, ramo e condizione, lettura di un rapporto, perché la copertur…

Leggi l'articolo →
Database e SQL

DELETE vs TRUNCATE vs DROP in SQL: differenze, rollback e quando utilizzarli

DELETE vs TRUNCATE vs DROP spiegato con SQL testato: cosa rimuove, rollback, trigger, reimpostazione dell'identità, velocità e come differiscono Pos…

Leggi l'articolo →
Database e SQL

Spiegazione delle visualizzazioni SQL: crea, utilizza ed evita le insidie, con esempi

Viste SQL spiegate con le query che abbiamo eseguito: creazione di una vista, risultati in tempo reale, nascondere colonne, prestazioni, viste aggio…

Leggi l'articolo →
Sviluppo software

Interfaccia TypeScript e tipo: differenze reali, testate con il compilatore

Interfaccia TypeScript vs tipo, verificata con il vero compilatore: cosa possono fare entrambi, cosa può fare solo uno, fusione delle dichiarazioni,…

Leggi l'articolo →
Sviluppo software

Spiegazione di Python *args e **kwargs: funzioni flessibili con esempi chiari

Python *args e **kwargs spiegati con il codice che abbiamo eseguito: compressione e decompressione, ordine dei parametri, argomenti solo per parole …

Leggi l'articolo →
Sviluppo software

Funzioni Lambda Python: sintassi, usi reali e quando non usarli

Funzioni lambda Python spiegate con il codice che abbiamo eseguito: sintassi, ordinamento con chiave, mappa e filtro, chiusure, trap dell'associazio…

Leggi l'articolo →
Intelligenza artificiale

Cosa sono gli agenti AI? Come funzionano, con un semplice ciclo di agenti che puoi eseguire

Cosa sono gli agenti IA? Una semplice guida al ciclo dell'agente, agli strumenti, alla memoria e ai guardrail, con un piccolo ciclo Python che abbia…

Leggi l'articolo →
DevOps

Monitoraggio vs osservabilità: la vera differenza, con log, metriche e tracce

Spiegazione del monitoraggio e dell'osservabilità: errori noti e sconosciuti, log, metriche e tracce, una procedura dettagliata sugli incidenti di p…

Leggi l'articolo →
DevOps

Volumi Docker e montaggi di associazione: mantenere i dati del contenitore nel modo giusto

Volumi Docker e montaggi di collegamento spiegati: perché i dati del contenitore scompaiono, volumi denominati, montaggi di collegamento, tmpfs, ese…

Leggi l'articolo →
Automazione dei test

TDD vs BDD: differenze chiave, una caratteristica costruita in entrambi i modi e quando utilizzarli ciascuno

TDD vs BDD spiegato con una funzione di sconto costruita in entrambi i modi: refactoring rosso-verde con il codice che abbiamo eseguito, scenari "Da…

Leggi l'articolo →
Test del software

Test di accettazione da parte dell'utente (UAT): processo, lista di controllo ed esempi reali

Spiegazione del test di accettazione dell'utente: chi lo esegue, in cosa differisce dal QA, un processo in sette fasi, un modello di test case UAT, …

Leggi l'articolo →
Database e SQL

Spiegazione dei valori SQL NULL: IS NULL, COALESCE, NULLIF e le trappole da evitare

Valori SQL NULL spiegati con le query che abbiamo eseguito: logica a tre valori, IS NULL, COALESCE, NULLIF, come aggregazioni, join e ordinamento tr…

Leggi l'articolo →
Database e SQL

Istruzione SQL CASE WHEN: sintassi, esempi reali ed errori comuni

SQL CASE WHEN spiegato con le query che abbiamo eseguito: moduli semplici e cercati, ordine delle condizioni, pivot con SUM, trucchi COUNT, ordiname…

Leggi l'articolo →
Sviluppo software

Cos'è il JWT? Token Web JSON spiegati con un esempio funzionante

Cos'è il JWT? Spiegazione dei token Web JSON: le tre parti, un token creato e manomesso nel codice che abbiamo eseguito, JWT e sessioni, archiviazio…

Leggi l'articolo →
Sviluppo software

Spiegazione del loop di eventi JavaScript: stack di chiamate, microtask e timer con esempi

Il ciclo di eventi JavaScript spiegato con il codice che abbiamo eseguito: stack di chiamate, code di attività e microtask, perché setTimeout 0 non …

Leggi l'articolo →
Sviluppo software

Spiegazione dei generatori Python e del rendimento: risparmia memoria con esempi reali

Generatori Python e rendimento spiegati con il codice che abbiamo eseguito: come vengono messi in pausa e ripresi, misurato il risparmio di memoria,…

Leggi l'articolo →
Intelligenza artificiale

Cosa sono gli incorporamenti? I vettori e la somiglianza del coseno spiegati semplicemente

Cosa sono gli incorporamenti? Una guida in linguaggio semplice ai vettori, alla similarità del coseno e alla ricerca semantica, con un piccolo esemp…

Leggi l'articolo →
DevOps

Distribuzione blu-verde rispetto a quella canaria: differenze, compromessi e come scegliere

Spiegazione della distribuzione blu-verde e canary: come funziona ciascuna, costi, rischi e rollback, bucket utente stabile che abbiamo testato, mig…

Leggi l'articolo →
Automazione dei test

Test instabili: quali sono le cause e come risolverli definitivamente

Test instabili spiegati con demo che abbiamo eseguito: le cause principali, come confermarne e diagnosticarne uno, soluzioni adeguate per tempistich…

Leggi l'articolo →
Test del software

Test di carico e test di stress: differenze, metriche ed esempi k6

Spiegazione del test di carico e dello stress test: cosa dimostra ciascuno, test di picco e di assorbimento, le metriche che contano, perché le medi…

Leggi l'articolo →
Test del software

Caso di test e scenario di test: differenze chiave, esempi e quando utilizzarli

Spiegazione del caso di test e dello scenario di test: definizioni chiare, una tabella affiancata, una funzione di reimpostazione della password pre…

Leggi l'articolo →
Database e SQL

Ottimizzazione delle query SQL: leggi i piani di esecuzione e correggi query lente, con tempistiche

Ottimizzazione delle query SQL testata su un milione di righe: leggi i piani di esecuzione, aggiungi gli indici corretti, correggi filtri non aggior…

Leggi l'articolo →
Database e SQL

SQL UNION vs UNION ALL: differenze, esempi e prestazioni testate

SQL UNION vs UNION ALL spiegati con le query che abbiamo eseguito: duplicati, regole seguite da entrambi, un vero bug di dati, prestazioni misurate,…

Leggi l'articolo →
Sviluppo software

Tutorial sull'API di recupero JavaScript: GET, POST, gestione degli errori e timeout

Un tutorial sull'API JavaScript Fetch testato su un server locale: GET e POST, perché 404 non genera eccezioni, un helper riutilizzabile, stringhe d…

Leggi l'articolo →
Sviluppo software

Gestione dei file Python: lettura, scrittura, CSV, JSON e pathlib con esempi

Gestione dei file Python spiegata con il codice che abbiamo eseguito: modalità aperte, con, lettura di file di grandi dimensioni, CSV, JSON, pathlib…

Leggi l'articolo →
Sviluppo software

Classi e oggetti Python: tutorial OOP con esempi reali

Classi e oggetti Python spiegati con il codice che abbiamo eseguito: __init__, metodi, attributi di classe e istanza, ereditarietà, proprietà, metod…

Leggi l'articolo →
Intelligenza artificiale

Che cos'è un modello linguistico di grandi dimensioni? Come funzionano i LLM, spiegato senza esagerazioni

Cos’è un modello linguistico ampio? LLM spiegati in un linguaggio semplice: token, incorporamenti, attenzione, formazione, finestre di temperatura e…

Leggi l'articolo →
DevOps

Comandi Linux per principianti: la guida essenziale del terminale con esempi

Comandi Linux per principianti, raggruppati per attività: navigazione, file, visualizzazione log, grep, pipe, permessi, processi e archivi, con un e…

Leggi l'articolo →
Automazione dei test

Selenio vs drammaturgo: differenze chiave, codice a confronto e quale scegliere

Selenium vs Playwright a confronto: architettura, attesa, supporto per browser e linguaggio, debug, lo stesso test in entrambi gli strumenti, consig…

Leggi l'articolo →
Test del software

Partizionamento di equivalenza: tecnica di progettazione dei test spiegata con esempi pratici

Spiegazione del partizionamento di equivalenza: come trovare partizioni valide e non valide, esempi funzionanti per età, password e coupon, test che…

Leggi l'articolo →
Test del software

Gravità vs priorità nel test del software: differenze, matrice ed esempi reali

Spiegazione della gravità e della priorità nei test del software: definizioni chiare, una matrice a quattro vie con esempi, scale di livello, chi im…

Leggi l'articolo →
Database e SQL

Esercitazione sulle sottoquery SQL: tipi, sottoquery correlate ed EXISTS con esempi

Un tutorial sulle sottoquery SQL con le query che abbiamo eseguito: sottoquery scalari, IN, FROM e SELECT, sottoquery correlate, EXISTS, trap NOT IN…

Leggi l'articolo →
Database e SQL

Spiegazione di transazioni SQL e ACID: COMMIT, ROLLBACK e livelli di isolamento

Transazioni SQL e ACID spiegate con un bonifico bancario eseguito: COMMIT, ROLLBACK, punti di salvataggio, blocchi, livelli di isolamento, letture s…

Leggi l'articolo →
Sviluppo software

Git merge vs rebase: differenze, esempi e quando usare ciascuno

Git merge vs rebase spiegato con output reale del log, una tabella di confronto, la regola d'oro del rebase e un flusso di lavoro sicuro per i team.

Leggi l'articolo →
Sviluppo software

List comprehension in Python: sintassi, esempi e quando evitarla

List comprehension in Python spiegata: sintassi, filtri, if-else, cicli annidati, tempi misurati e i casi in cui un normale ciclo for è meglio.

Leggi l'articolo →
Database e SQL

SQL JOIN spiegati con esempi (Inner, Left, Right, Full)

Capisci i JOIN SQL passo dopo passo con tabelle e query di esempio: INNER, LEFT, RIGHT, FULL, CROSS e SELF, con errori comuni e consigli sulle prest…

Leggi l'articolo →