modulo 16 di 24 / Ore 21-40

Moduli 9-16 / Checkpoint 40 ore

Controllare test e casi limite

Come verificare manualmente che i test del Registro coprano i casi limite: lista vuota, ID inesistente, strumento guasto, doppia chiusura prestito.

25 min Architettura del software

Controllare test e casi limite

Questa lezione appartiene al Modulo 16 — Checkpoint a 20 ore.

Obiettivo della lezione

Verificare che la suite di test del Registro copra i casi limite più importanti — non solo il caso felice, ma le situazioni al confine tra corretto e scorretto che rivelano i bug più comuni.

Alla fine hai una checklist dei casi limite verificati e sai quali aggiungere se mancano.

Perché serve nel percorso

I casi limite sono quelli che la maggior parte degli sviluppatori dimentica di testare: lista vuota, ID inesistente, strumento già nello stato sbagliato, doppia operazione sullo stesso oggetto. Sono esattamente i casi che si presentano durante l’uso reale e che provocano crash o comportamenti imprevisti.

Nel Registro del laboratorio

I casi limite più importanti per il Registro sono organizzati per area:

Casi limite sugli strumenti

// test/application/registraStrumento.test.js

test("registraStrumento — lancia errore per nome vuoto", () => {
  const archivio = creaArchivioStrumentiFake();
  expect(() => registraStrumento({ nome: "", categoria: "Misura" }, archivio))
    .toThrow("NOME_STRUMENTO_NON_VALIDO");
});

test("registraStrumento — lancia errore per nome di soli spazi", () => {
  const archivio = creaArchivioStrumentiFake();
  expect(() => registraStrumento({ nome: "   ", categoria: "Misura" }, archivio))
    .toThrow("NOME_STRUMENTO_NON_VALIDO");
});

test("cercaStrumenti — restituisce lista vuota se l'archivio è vuoto", () => {
  const archivio = creaArchivioStrumentiFake([]); // archivio senza strumenti
  const risultato = cercaStrumenti({}, archivio);
  expect(risultato).toEqual([]);
});

test("cercaStrumenti — restituisce lista vuota se nessuno strumento corrisponde al filtro", () => {
  const archivio = creaArchivioStrumentiFake([
    { id: "s1", nome: "Trapano", categoria: "Utensile", stato: "disponibile" }
  ]);
  const risultato = cercaStrumenti({ categoria: "Misura" }, archivio);
  expect(risultato).toEqual([]);
});

Casi limite sui prestiti

// test/application/registraPrestito.test.js

test("registraPrestito — lancia STRUMENTO_NON_TROVATO per ID inesistente", () => {
  const strumenti = creaArchivioStrumentiFake([]); // archivio vuoto
  const prestiti = creaArchivioPrestitiFake();
  expect(() =>
    registraPrestito({ strumentoId: "non-esiste", studenteId: "stu-01" }, strumenti, prestiti)
  ).toThrow("STRUMENTO_NON_TROVATO");
});

test("registraPrestito — lancia errore per strumento guasto", () => {
  const strumenti = creaArchivioStrumentiFake([
    { id: "s1", nome: "Trapano", categoria: "Utensile", stato: "guasto" }
  ]);
  expect(() =>
    registraPrestito({ strumentoId: "s1", studenteId: "stu-01" }, strumenti, creaArchivioPrestitiFake())
  ).toThrow("STRUMENTO_GUASTO_NON_PRESTABILE");
});

// test/application/chiudiPrestito.test.js

test("chiudiPrestito — lancia PRESTITO_NON_TROVATO per ID inesistente", () => {
  const prestiti = creaArchivioPrestitiFake([]); // archivio vuoto
  expect(() => chiudiPrestito({ prestitoId: "non-esiste" }, prestiti))
    .toThrow("PRESTITO_NON_TROVATO");
});

test("chiudiPrestito — lancia PRESTITO_GIA_CHIUSO per prestito già chiuso", () => {
  const prestiti = creaArchivioPrestitiFake([
    { id: "p1", strumentoId: "s1", studenteId: "stu-01", apertura: new Date(), chiusura: new Date() }
  ]);
  expect(() => chiudiPrestito({ prestitoId: "p1" }, prestiti))
    .toThrow("PRESTITO_GIA_CHIUSO");
});

Procedura guidata

  1. Elenca tutti i casi limite del Registro (usa la lista in questa lezione come punto di partenza).
  2. Per ogni caso limite: cerca il test corrispondente in test/.
  3. Se il test manca: scrivilo.
  4. Esegui i test: se un test fallisce, hai trovato un bug da correggere.
  5. Documenta i casi limite coperti nella scheda.

Attività in classe

Verifica questa lista di casi limite e segna quelli coperti e quelli mancanti nel tuo progetto:

## Checklist casi limite

Strumenti:
[ ] nome vuoto lancia errore
[ ] nome di soli spazi lancia errore
[ ] nome troppo lungo lancia errore
[ ] lista vuota restituisce array vuoto (non undefined)
[ ] filtro senza corrispondenze restituisce array vuoto

Prestiti:
[ ] ID strumento inesistente lancia STRUMENTO_NON_TROVATO
[ ] strumento guasto lancia errore
[ ] strumento in prestito lancia errore (doppio prestito)
[ ] ID prestito inesistente per chiusura lancia errore
[ ] prestito già chiuso lancia PRESTITO_GIA_CHIUSO

Infrastruttura:
[ ] localStorage vuoto restituisce lista vuota (non crash)
[ ] localStorage con JSON corrotto restituisce lista vuota (non crash)

Spiegazione guidata per studiare

I casi limite si dividono in due categorie:

Casi limite di input: valori al confine del range valido — stringa vuota, stringa di soli spazi, valore null, ID che non esiste. Questi rivelano le validazioni mancanti.

Casi limite di stato: oggetti in stati particolari — strumento guasto, prestito già chiuso, archivio vuoto. Questi rivelano le regole mancanti o le condizioni non gestite.

Il modo più rapido per trovare i casi limite mancanti: leggi ogni funzione del dominio e immagina cosa succede se riceve input “al bordo”. Per validaNomeStrumento:

  • "" (stringa vuota) → deve lanciare errore
  • " " (solo spazi) → dopo il trim() diventa "" → deve lanciare errore
  • "A" (1 carattere) → sotto il minimo → deve lanciare errore
  • "A".repeat(81) (81 caratteri) → sopra il massimo → deve lanciare errore
  • "AB" (2 caratteri) → il minimo valido → deve passare

Cinque test per una funzione di validazione minima. Nessuno è ovvio — tutti rivelano qualcosa.

Passo per passo nel progetto

  1. Apri la checklist e segna i casi limite già coperti.
  2. Per ogni caso non coperto: scrivi il test prima di correggere il codice.
  3. Esegui il test — se fallisce, hai trovato un bug reale.
  4. Correggi il bug.
  5. Riesegui il test — deve passare.
  6. Aggiungi il caso alla checklist come “coperto”.

Prova di comprensione

  • Qual è la differenza tra un caso felice e un caso limite?
  • Come si gestisce il caso “lista vuota” nell’adapter di localStorage?
  • Cosa succede se trovaPerId riceve un ID che non esiste — cosa restituisce?
  • Perché è importante testare nome = " " (spazi) separatamente da nome = ""?

Errori da evitare

  • testare solo il caso felice — i bug reali vivono nei casi limite;
  • scrivere il test dopo aver già corretto il bug — non sai se il test avrebbe trovato il problema;
  • ignorare il caso “archivio vuoto” — è il primo stato di ogni nuova installazione del Registro;
  • confondere “il test passa” con “il comportamento è corretto” — un test mal scritto può passare anche se il bug esiste.

Prodotto da consegnare

La checklist compilata con tutti i casi limite del Registro, i test mancanti aggiunti, e l’output del runner che mostra che tutti i casi limite sono coperti.

Checklist di chiusura

  • ogni caso limite nella lista è segnato come coperto o mancante
  • i casi limite mancanti hanno un test aggiunto
  • i test scritti falliscono prima della correzione e passano dopo
  • l’output del runner mostra i casi limite tra i test che passano
  • nessun test usa undefined o null come risultato atteso senza una motivazione esplicita

Risultato atteso

Ho verificato la checklist dei casi limite del Registro.
5 casi erano già coperti, 4 mancavano (lista vuota, JSON corrotto, spazi nel nome, doppio prestito).
Ho scritto i 4 test mancanti — 2 hanno trovato bug reali che ho corretto.
Ora tutti i casi limite nella checklist sono coperti.
L'output del runner mostra 16 test che passano, inclusi i 4 nuovi.