modulo 13 di 24 / Ore 21-40
Moduli 9-16 / Checkpoint 40 ore
Testare un caso d'uso senza browser
Come testare registraPrestito senza browser usando archivio in memoria — setup del test, verifica del comportamento, verifica dello stato finale degli archivi, confronto con un test che richiederebbe il browser.
Testare un caso d’uso senza browser
Questa lezione appartiene al Modulo 13 — Testare l’architettura.
Un test che richiede il browser è un test lento, fragile e difficile da automatizzare. Se l’architettura è fatta bene, il caso d’uso principale del Registro — registraPrestito — può essere testato completamente da terminale, in pochi millisecondi, senza aprire nessuna pagina.
Obiettivo della lezione
In questa lezione impari a testare registraPrestito senza browser, usando archivi in memoria al posto di localStorage. Verifichi il comportamento, lo stato finale di entrambi gli archivi, e capisci cosa renderebbe necessario il browser e come evitarlo.
Alla fine devi avere un risultato verificabile: un test completo di registraPrestito che gira con node da terminale e copre il caso felice e due casi limite.
Perché “senza browser” è importante
Un test che richiede il browser ha questi problemi:
- è lento (avvio del browser, rendering della pagina);
- dipende da HTML e DOM, che cambiano spesso;
- non può girare in un ambiente di CI senza configurazione speciale;
- fallisce per ragioni non legate alla logica di business.
Se registraPrestito fosse scritto così:
function registraPrestito(idStrumento, nomeStudente) {
const raw = localStorage.getItem('registro_strumenti'); // dipendenza dal browser
// ...
}
non potresti testarlo senza browser. Ogni test richiederebbe un ambiente con window.localStorage.
Se invece registraPrestito riceve gli archivi come parametri (o li importa da un modulo sostituibile), puoi passare archivi in memoria e il browser non serve mai.
Il setup del test
Per testare registraPrestito senza browser, hai bisogno di:
- Un archivio strumenti in memoria con almeno uno strumento disponibile.
- Un archivio prestiti in memoria, inizialmente vuoto.
- La funzione
registraPrestitoche accetta questi archivi come dipendenze.
Il setup tipico è questo:
// Per ogni test, parti da zero
const archivioStr = creaArchivioStrumentiInMemoria([
{ id: 'id-trapano', nome: 'Trapano Bosch', categoria: 'elettrico', stato: 'disponibile' }
]);
const archivioPrest = creaArchivioPrestitiInMemoria([]);
Dopo registraPrestito, verifichi lo stato finale di entrambi gli archivi.
Le verifiche da fare
Un test completo di registraPrestito deve verificare:
Verifica 1 — Il prestito è stato salvato
archivioPrest.tutti().length === 1
Verifica 2 — Il prestito ha i campi corretti
prestito.idStrumento === 'id-trapano'
prestito.nomeStudente === 'Mario Rossi'
prestito.stato === 'aperto'
prestito.dataApertura !== undefined
Verifica 3 — Lo strumento ha cambiato stato
archivioStr.trova('id-trapano').stato === 'in_prestito'
Verifica 4 — Il caso d'uso restituisce il prestito
risultato.id !== undefined
Procedura guidata
- Crea o apri
test/registraPrestito.test.js. - Scrivi il setup: archivio strumenti con uno strumento disponibile, archivio prestiti vuoto.
- Chiama
registraPrestito('id-trapano', 'Mario Rossi', archivioStr, archivioPrest). - Verifica il prestito nell’archivio: conta gli elementi, controlla i campi.
- Verifica lo stato dello strumento nell’archivio strumenti.
- Aggiungi il test del caso limite: strumento guasto.
- Aggiungi il test del caso limite: nome vuoto.
- Esegui
node test/registraPrestito.test.jse verifica che tutti i test passino.
Attività in classe
Descrivi il setup e le verifiche prima di scrivere il codice:
## Test registraPrestito senza browser
Setup per il caso felice:
archivioStr contiene: _______________
archivioPrest contiene: _______________
Verifiche dopo registraPrestito('id-trapano', 'Mario Rossi'):
Verifica 1: archivioPrest.tutti().length === _______________
Verifica 2: prestito.stato === _______________
Verifica 3: archivioStr.trova('id-trapano').stato === _______________
Verifica 4: il valore restituito ha il campo: _______________
Cosa renderebbe questo test dipendente dal browser?
(elenca le dipendenze da evitare)
_______________
_______________
Se lavori in gruppo, una persona descrive il setup e un’altra scrive il codice del test.
Spiegazione guidata per studiare
Un caso d’uso senza browser è possibile solo se il caso d’uso non conosce i dettagli di dove i dati sono salvati. Se registraPrestito chiama direttamente localStorage.setItem, l’unico modo per testarlo è avere un browser con localStorage. Ma se riceve l’archivio come parametro (o lo importa da un modulo che puoi sostituire nel test), puoi passare qualsiasi implementazione tu voglia.
Questo è il valore pratico della separazione tra Application e Infrastructure. Non è una questione di organizzazione delle cartelle: è che il test del caso d’uso più importante del sistema può girare senza browser, in meno di un secondo, senza configurazione.
Quando studi, chiediti: “se dovessi testare questo caso d’uso senza browser, cosa dovrei cambiare?” Se la risposta è “niente, basta passare un archivio in memoria”, l’architettura è buona. Se la risposta è “dovrei riscrivere il caso d’uso”, c’è un accoppiamento nascosto da correggere.
Il confronto con un test che richiederebbe il browser è utile per capire il valore della separazione. Immagina di dover testare registraPrestito con un browser: dovresti caricare la pagina, compilare il form, cliccare il pulsante, leggere il messaggio. Il test durerebbe secondi invece di millisecondi e dipendrebbe dall’HTML. Con l’archivio in memoria, il test è quattro righe di setup e cinque asserzioni.
Passo per passo nel progetto
- Apri
application/registraPrestito.jse verifica come riceve gli archivi: come parametri o come importazioni dirette. - Se li importa direttamente, refactorizza per riceverli come parametri — questo è il prerequisito per testare senza browser.
- Crea
test/registraPrestito.test.jscon il setup descritto sopra. - Scrivi il test del caso felice e verifica che passi.
- Scrivi il test con strumento guasto: stesso setup ma stato
'guasto', verifica l’errore. - Scrivi il test con nome vuoto: stesso setup ma nome
'', verifica l’errore. - Esegui tutti i test e verifica l’output.
Esempio da leggere lentamente
Questo test completo mostra il caso felice e due casi limite, senza nessuna dipendenza dal browser:
// test/registraPrestito.test.js
import { registraPrestito } from '../application/registraPrestito.js';
import {
creaArchivioStrumentiInMemoria,
creaArchivioPrestitiInMemoria
} from './supporto/archivioInMemoria.js';
// Caso felice: apertura di un prestito su strumento disponibile
function testCasoFelice() {
const archivioStr = creaArchivioStrumentiInMemoria([
{ id: 'id-trapano', nome: 'Trapano Bosch', categoria: 'elettrico', stato: 'disponibile' }
]);
const archivioPrest = creaArchivioPrestitiInMemoria([]);
const prestito = registraPrestito('id-trapano', 'Mario Rossi', archivioStr, archivioPrest);
// Verifica 1: il prestito è stato salvato nell'archivio
const tutti = archivioPrest.tutti();
if (tutti.length !== 1) throw new Error('Atteso 1 prestito, trovati: ' + tutti.length);
// Verifica 2: il prestito ha i campi corretti
if (prestito.idStrumento !== 'id-trapano') throw new Error('idStrumento errato');
if (prestito.nomeStudente !== 'Mario Rossi') throw new Error('nomeStudente errato');
if (prestito.stato !== 'aperto') throw new Error('stato prestito non è aperto');
if (!prestito.dataApertura) throw new Error('dataApertura mancante');
// Verifica 3: lo strumento ha cambiato stato
const strumento = archivioStr.trova('id-trapano');
if (strumento.stato !== 'in_prestito') {
throw new Error('Lo strumento deve essere in_prestito, trovato: ' + strumento.stato);
}
console.log('OK — caso felice: prestito registrato correttamente');
}
// Caso limite: strumento guasto
function testStrumentoGuasto() {
const archivioStr = creaArchivioStrumentiInMemoria([
{ id: 'id-sega', nome: 'Sega circolare', stato: 'guasto' }
]);
const archivioPrest = creaArchivioPrestitiInMemoria([]);
let errore = null;
try {
registraPrestito('id-sega', 'Luigi Bianchi', archivioStr, archivioPrest);
} catch (e) {
errore = e;
}
if (!errore) throw new Error('Atteso errore per strumento guasto');
if (!errore.message.includes('non è disponibile')) {
throw new Error('Messaggio errore non corretto: ' + errore.message);
}
// Verifica che l'archivio prestiti sia rimasto vuoto
if (archivioPrest.tutti().length !== 0) {
throw new Error('Non deve essere salvato nessun prestito per strumento guasto');
}
console.log('OK — strumento guasto rifiutato, nessun prestito salvato');
}
// Caso limite: nome studente vuoto
function testNomeVuoto() {
const archivioStr = creaArchivioStrumentiInMemoria([
{ id: 'id-martello', nome: 'Martello', stato: 'disponibile' }
]);
const archivioPrest = creaArchivioPrestitiInMemoria([]);
let errore = null;
try {
registraPrestito('id-martello', ' ', archivioStr, archivioPrest); // solo spazi
} catch (e) {
errore = e;
}
if (!errore) throw new Error('Atteso errore per nome vuoto');
if (!errore.message.includes('obbligatorio')) {
throw new Error('Messaggio errore non corretto: ' + errore.message);
}
console.log('OK — nome vuoto rifiutato');
}
testCasoFelice();
testStrumentoGuasto();
testNomeVuoto();
console.log('\nTutti i test di registraPrestito passati. Nessun browser richiesto.');
Nota: nessuna riga di codice fa riferimento a localStorage, document, window o fetch. Il test gira con Node.js puro.
Prova di comprensione
Prima di chiudere la lezione, rispondi per iscritto a queste domande:
- Cosa renderebbe
registraPrestitoimpossibile da testare senza browser? - Perché il test del caso limite “strumento guasto” verifica anche che l’archivio prestiti sia rimasto vuoto?
- Se
registraPrestitoimportaarchivioStrumentiLocaledirettamente (non come parametro), come puoi comunque testarlo senza browser? - Qual è la differenza tra “testare senza browser” e “testare senza UI”?
Una risposta accettabile usa i nomi reali dei file e delle funzioni del progetto.
Errori da evitare
- testare solo il caso felice senza i casi limite;
- non verificare lo stato finale dell’archivio strumenti — un test che controlla solo il prestito manca metà delle verifiche importanti;
- condividere lo stesso archivio tra i test — i dati del primo test alterano il secondo;
- chiamare
localStoragenel test in modo diretto — l’archivio in memoria esiste proprio per evitarlo; - non verificare che l’archivio prestiti sia vuoto dopo un errore — il sistema non deve salvare dati parziali.
Prodotto da consegnare
Crea o aggiorna test/registraPrestito.test.js con i tre test descritti in questa lezione. Il file deve girare con node test/registraPrestito.test.js senza errori e stampare tre righe “OK” seguite dal messaggio finale.
Checklist di chiusura
Prima di chiudere la lezione, controlla:
- il test del caso felice verifica il prestito nell’archivio, i campi del prestito e lo stato dello strumento;
- il test del caso limite “strumento guasto” verifica anche che l’archivio prestiti sia rimasto vuoto;
- il test del caso limite “nome vuoto” usa una stringa di solo spazi per simulare un campo quasi vuoto;
- nessun test importa
localStorage,documentowindow; - i test girano con
nodesenza browser.
Risultato atteso
Alla fine lo studente deve saper dire:
Ho testato registraPrestito senza browser usando archivi in memoria.
Il test del caso felice verifica il prestito salvato, i campi e lo stato dello strumento.
Il test del caso limite "strumento guasto" verifica l'errore e che nessun prestito venga salvato.
Il test del caso limite "nome vuoto" verifica che anche gli spazi vengano rifiutati.
I test girano con node da terminale in meno di un secondo, senza aprire nessuna pagina.
Se questa spiegazione non è possibile, la lezione non è ancora davvero conclusa.