Il test automatico sarà utilizzato per molte attività.
Fa parte della “preparazione minima” di uno sviluppatore.
Perché sono necessari i test?
Quando scriviamo una funzione, spesso possiamo immaginare quello che deve fare: i parametri necessari e i risultati restituiti.
Durante lo sviluppo, possiamo controllare le funzioni eseguendole e controllando se i risultati sono quelli aspettati. Ad esempio possiamo farlo tramite la console.
Se qualcosa non funziona – allora possiamo sistemare il codice, rieseguirlo e controllare nuovamente il risultato – e continuare a ripetere questa procedura fino a risolvere il bug.
Ma alcuni test manuali non sono sempre perfetti.
Quando testiamo il codice manualmente rieseguendolo, è facile dimenticare qualcosa.
Ad esempio, stiamo creando una funzione f. Scriviamo del codice, lo testiamo con: f(1) e funziona, ma con f(2) non funziona. Sistemiamo il codice e ora f(2) funziona. Il test sembra completo? Invece ci siamo dimenticati di ri-testare f(1). Questo infatti potrebbe contenere un errore.
Questo è un errore tipico. Quando sviluppiamo qualcosa, cerchiamo di tenere a mente molti possibili casi di utilizzo. Ma è difficile aspettarsi che un programmatore controlli a mano il risultato dopo ogni cambiamento. Diventa quindi facile sistemare una bug e crearne uno di nuovo.
Test automatici significa che i test vengono scritti separati, e sono complementari al codice. Possono essere facilmente eseguiti ed utilizzati per controllare i principali casi di utilizzo.
Behavior Driven Development (BDD)
Utilizziamo una tecnica chiamata Behavior Driven Development o, in breve, BDD. Questo approccio viene utilizzato in moltissimi progetti. BDD non offre solo testing, ha molte altre funzionalità.
BDD contiene tre cose in una: test, documentazione ed esempi.
Abbiamo parlato abbastanza. Vediamo degli esempi.
Sviluppo di “pow”: le specifiche
Vogliamo creare una funzione pow(x, n) che calcola la potenza di x per un intero n. Assumiamo che n≥0.
Questo è solo un esempio: infatti l’operatore ** svolge quest’azione, ma concentriamoci sul flusso di sviluppo, che potremmo poi applicare a funzioni più complesse.
Prima di scrivere il codice di pow, possiamo immaginare cosa vogliamo che la funzione faccia e descriverlo.
Questa descrizione viene chiamata specifica o, in breve, spec, ed appare cosi:
describe("pow", function() {
it("raises to n-th power", function() {
assert.equal(pow(2, 3), 8);
});
});
Una spec ha tre principali blocchi:
describe("title", function() { ... })-
Viene descritta la funzionalità. Utilizzata per raggruppare le “attività” – i blocchi
it. Nel nostro caso descriviamo la funzionepow. it("title", function() { ... })-
Nel titolo di
itdescriviamo il particolare caso d’uso leggibile per gli umani, come secondo argomento una funzione che lo testa. assert.equal(value1, value2)-
Il codice all’interno del blocco
it, se l’implementazione è corretta, dovrebbe eseguire senza errori.Le funzioni
assert.*vengono utilizzate per controllare che