modulo 13 di 24 / Ore 21-40
Moduli 9-16 / Checkpoint 40 ore
Testare apertura e chiusura di un prestito
Come scrivere test concreti per aprire e chiudere un prestito nel Registro — con archivio in memoria, verifica dello stato dello strumento dopo il prestito, e verifica che chiudere un prestito già chiuso lanci l'errore corretto.
Testare apertura e chiusura di un prestito
Questa lezione appartiene al Modulo 13 — Testare l’architettura.
Un prestito ha due operazioni principali: l’apertura e la chiusura. Per ognuna devi avere un test che verifica il comportamento atteso. Non basta che “funzioni nel browser”: devi poter eseguire il test da terminale, senza UI, senza localStorage, e ottenere una risposta precisa.
Obiettivo della lezione
In questa lezione scrivi test concreti per registraPrestito e chiudiPrestito usando un archivio in memoria. Verifichi che lo stato dello strumento cambi correttamente, che il prestito venga salvato con i campi giusti, e che tentare di chiudere un prestito già chiuso lanci l’errore corretto.
Alla fine devi avere un risultato verificabile: almeno quattro test che girano con node da terminale.
Le quattro verifiche da fare
Per ogni test devi sapere in anticipo cosa stai verificando. Ecco le quattro verifiche principali:
TEST 1 — Apertura prestito
Input: strumento disponibile, nome studente valido
Verifica 1: il prestito restituito ha stato 'aperto'
Verifica 2: lo strumento nell'archivio ha stato 'in_prestito'
Verifica 3: il prestito ha nomeStudente, dataApertura, idStrumento
TEST 2 — Chiusura prestito
Input: prestito aperto esistente
Verifica 1: il prestito nell'archivio ha stato 'chiuso'
Verifica 2: lo strumento ha stato 'disponibile'
Verifica 3: il prestito ha una dataChiusura
TEST 3 — Chiusura di un prestito già chiuso
Input: prestito con stato 'chiuso'
Verifica: viene lanciato un errore con messaggio appropriato
TEST 4 — Apertura su strumento non disponibile
Input: strumento con stato 'in_prestito'
Verifica: viene lanciato un errore "Lo strumento non è disponibile"
L’archivio in memoria per i test
Per testare senza localStorage, costruisci un archivio in memoria che implementa la stessa interfaccia di quello reale:
// test/supporto/archivioInMemoria.js
function creaArchivioStrumentiInMemoria(strumentiIniziali = []) {
const strumenti = [...strumentiIniziali];
return {
trova(id) {
return strumenti.find(s => s.id === id) || null;
},
salva(strumento) {
strumenti.push(strumento);
},
aggiornaStato(id, nuovoStato) {
const s = strumenti.find(s => s.id === id);
if (s) s.stato = nuovoStato;
},
tutti() {
return [...strumenti];
}
};
}
function creaArchivioPrestitiInMemoria(prestitiIniziali = []) {
const prestiti = [...prestitiIniziali];
return {
trova(id) {
return prestiti.find(p => p.id === id) || null;
},
salva(prestito) {
prestiti.push(prestito);
},
aggiorna(id, modifiche) {
const p = prestiti.find(p => p.id === id);
if (p) Object.assign(p, modifiche);
},
tutti() {
return [...prestiti];
}
};
}
Questo archivio non tocca localStorage. Funziona con un array in memoria. È testabile, prevedibile, resettabile a ogni test.
Procedura guidata
- Crea il file
test/supporto/archivioInMemoria.jscon le due funzioni di factory. - Crea il file
test/prestito.test.jscon i quattro test. - Per ogni test, crea un archivio fresco (non condividere lo stesso archivio tra test).
- Esegui il primo test: apertura del prestito. Verifica lo stato dello strumento.
- Esegui il secondo test: chiusura del prestito. Verifica che lo strumento torni disponibile.
- Esegui il terzo test: chiusura di un prestito già chiuso. Verifica il lancio dell’errore.
- Esegui
node test/prestito.test.jsda terminale e verifica che tutti e quattro i test passino.
Attività in classe
Scrivi il comportamento atteso prima del codice:
## Test per apertura e chiusura prestito
Test 1 — Apertura
Setup: strumento { id: 'id-1', nome: 'Trapano', stato: 'disponibile' }
Azione: registraPrestito('id-1', 'Mario Rossi')
Verifica A: prestito.stato === _______________
Verifica B: strumento.stato === _______________
Verifica C: prestito.nomeStudente === _______________
Test 2 — Chiusura
Setup: prestito aperto con id 'prest-1', strumento 'id-1' in_prestito
Azione: chiudiPrestito('prest-1')
Verifica A: prestito.stato === _______________
Verifica B: strumento.stato === _______________
Verifica C: prestito.dataChiusura !== _______________
Test 3 — Chiusura già chiuso
Setup: prestito con stato 'chiuso'
Azione: chiudiPrestito('prest-1')
Verifica: errore.message contiene _______________
Spiegazione guidata per studiare
Un test di comportamento verifica tre cose: che l’azione sia possibile, che l’azione produca l’effetto atteso, e che le azioni non permesse vengano rifiutate.
Per l’apertura di un prestito, l’effetto atteso è doppio: il prestito viene creato e lo strumento cambia stato. Non basta verificare che il prestito esista — devi anche verificare che lo strumento sia passato da “disponibile” a “in_prestito”. Se uno dei due non avviene, c’è un bug.
Per la chiusura, il processo è simmetrico: il prestito passa da “aperto” a “chiuso” e lo strumento torna “disponibile”. In più, il prestito deve avere una dataChiusura.
Il test più importante è spesso quello dell’errore: cosa succede quando cerchi di chiudere un prestito già chiuso? Il sistema deve rifiutare l’operazione con un messaggio chiaro. Se non lo rifiuta, due chiamate consecutive a chiudiPrestito producono uno stato inconsistente.
Il pattern con archivio in memoria è il modo più pulito per scrivere questi test. Ogni test parte con un archivio fresco, nessun dato residuo da esecuzioni precedenti, nessuna dipendenza da localStorage. Il test è deterministico: produce sempre lo stesso risultato.
Passo per passo nel progetto
- Apri
application/registraPrestito.jse identifica cosa viene salvato negli archivi. - Apri (o crea)
application/chiudiPrestito.jse identifica cosa modifica. - Crea
test/supporto/archivioInMemoria.jscon le funzioni di factory. - Scrivi il test 1: crea un archivio con uno strumento disponibile, chiama
registraPrestito, verifica. - Scrivi il test 2: crea un archivio con un prestito aperto e lo strumento in_prestito, chiama
chiudiPrestito, verifica. - Scrivi il test 3: crea un archivio con un prestito già chiuso, chiama
chiudiPrestito, verifica l’errore. - Esegui
node test/prestito.test.jse leggi l’output.
Esempio da leggere lentamente
Questi test usano l’archivio in memoria per verificare apertura e chiusura:
// test/prestito.test.js
import { registraPrestito } from '../application/registraPrestito.js';
import { chiudiPrestito } from '../application/chiudiPrestito.js';
import {
creaArchivioStrumentiInMemoria,
creaArchivioPrestitiInMemoria
} from './supporto/archivioInMemoria.js';
function testAperturaPrestito() {
const archivioStr = creaArchivioStrumentiInMemoria([
{ id: 'id-1', nome: 'Trapano Bosch', stato: 'disponibile' }
]);
const archivioPrest = creaArchivioPrestitiInMemoria([]);
const prestito = registraPrestito('id-1', 'Mario Rossi', archivioStr, archivioPrest);
// verifica il prestito
if (prestito.stato !== 'aperto') throw new Error('Il prestito deve essere aperto');
if (prestito.nomeStudente !== 'Mario Rossi') throw new Error('Nome studente errato');
if (!prestito.dataApertura) throw new Error('Manca la dataApertura');
// verifica lo stato dello strumento
const strumento = archivioStr.trova('id-1');
if (strumento.stato !== 'in_prestito') {
throw new Error('Lo strumento deve essere in_prestito dopo il prestito');
}
console.log('OK — apertura prestito');
}
function testChiusuraPrestito() {
const archivioStr = creaArchivioStrumentiInMemoria([
{ id: 'id-1', nome: 'Trapano Bosch', stato: 'in_prestito' }
]);
const archivioPrest = creaArchivioPrestitiInMemoria([
{ id: 'prest-1', idStrumento: 'id-1', nomeStudente: 'Mario Rossi',
dataApertura: '2026-01-01T10:00:00.000Z', stato: 'aperto' }
]);
chiudiPrestito('prest-1', archivioStr, archivioPrest);
const prestito = archivioPrest.trova('prest-1');
if (prestito.stato !== 'chiuso') throw new Error('Il prestito deve essere chiuso');
if (!prestito.dataChiusura) throw new Error('Manca la dataChiusura');
const strumento = archivioStr.trova('id-1');
if (strumento.stato !== 'disponibile') {
throw new Error('Lo strumento deve tornare disponibile');
}
console.log('OK — chiusura prestito');
}
function testChiusuraGiaChiuso() {
const archivioStr = creaArchivioStrumentiInMemoria([
{ id: 'id-1', nome: 'Trapano Bosch', stato: 'disponibile' }
]);
const archivioPrest = creaArchivioPrestitiInMemoria([
{ id: 'prest-1', idStrumento: 'id-1', nomeStudente: 'Mario Rossi',
dataApertura: '2026-01-01T10:00:00.000Z',
dataChiusura: '2026-01-02T10:00:00.000Z',
stato: 'chiuso' }
]);
let erroreRicevuto = null;
try {
chiudiPrestito('prest-1', archivioStr, archivioPrest);
} catch (e) {
erroreRicevuto = e;
}
if (!erroreRicevuto) throw new Error('Il test doveva lanciare un errore');
if (!erroreRicevuto.message.includes('già chiuso')) {
throw new Error('Messaggio di errore non corretto: ' + erroreRicevuto.message);
}
console.log('OK — chiusura di prestito già chiuso rifiutata');
}
testAperturaPrestito();
testChiusuraPrestito();
testChiusuraGiaChiuso();
console.log('\nTutti i test passati.');
Prova di comprensione
Prima di chiudere la lezione, rispondi per iscritto a queste domande:
- Perché creare un archivio fresco per ogni test invece di condividerne uno?
- Quali due archivi devono essere aggiornati quando si apre un prestito?
- Se
chiudiPrestitonon aggiornadataChiusura, quale test lo scopre? - Cosa succede se esegui
testChiusuraGiaChiusodue volte con lo stesso archivio condiviso?
Una risposta accettabile usa i nomi reali delle funzioni e dei file del progetto.
Errori da evitare
- condividere lo stesso archivio tra test diversi — il test 2 troverebbe dati lasciati dal test 1;
- verificare solo il prestito senza verificare lo stato dello strumento;
- non testare il caso di errore — chiudere un prestito già chiuso è il caso limite più comune;
- passare
nullcome archivio senza gestirlo nel caso d’uso; - non avere
dataChiusuranel test di chiusura — è il campo che distingue aperto da chiuso.
Prodotto da consegnare
Crea il file test/prestito.test.js con i tre test descritti in questa lezione. Il file deve girare con node test/prestito.test.js senza errori e stampare tre righe “OK”.
Checklist di chiusura
Prima di chiudere la lezione, controlla:
- il test di apertura verifica sia il prestito sia lo stato dello strumento;
- il test di chiusura verifica che lo strumento torni disponibile;
- il test di chiusura verifica la presenza di
dataChiusura; - il test di chiusura già chiusa verifica il messaggio di errore;
- ogni test usa un archivio fresco, non condiviso.
Risultato atteso
Alla fine lo studente deve saper dire:
Ho scritto tre test per apertura e chiusura di un prestito.
Ogni test crea un archivio in memoria fresco con i dati di partenza.
Il test di apertura verifica il prestito creato e il cambio di stato dello strumento.
Il test di chiusura verifica stato 'chiuso', dataChiusura e che lo strumento torni disponibile.
Il test di errore verifica che chiudere un prestito già chiuso lanci l'eccezione corretta.
Se questa spiegazione non è possibile, la lezione non è ancora davvero conclusa.