I understand test-driven development so far that you are only allowed to write productive code when you have a failing (red) unit test.
No. È consentito solo scrivere il codice più semplice possibile per modificare il messaggio del test. Non dice nulla su che tipo di test.
In effetti, probabilmente inizierai scrivendo un test di accettazione (rosso) in errore per un criterio di accettazione, più precisamente, scrivi il test di accettazione più semplice che potrebbe fallire; successivamente esegui il test, guardalo fallire e verifica che non funzioni per il giusto motivo. Quindi si scrive un test funzionale in errore per una porzione di funzionalità di quel criterio di accettazione, ancora una volta si scrive il test funzionale più semplice che potrebbe fallire, eseguirlo, guardarlo fallire e verificare che non funzioni per il giusto motivo. Quindi scrivi un test dell'unità guasto, il test unitario più semplice che potrebbe fallire, eseguilo guardandolo fallire, verifica che non funzioni per il giusto motivo.
Ora , scrivi il codice di produzione più semplice che potrebbe modificare il messaggio di errore. Esegui nuovamente il test, verifica che il messaggio di errore sia cambiato, che sia cambiato nella giusta direzione e che il codice abbia cambiato il messaggio per il giusto motivo. (Idealmente, il messaggio di errore ora dovrebbe essere passato, e il test dovrebbe passare, ma il più delle volte, è meglio fare piccoli passi cambiando il messaggio invece di provare a far passare il test in un colpo solo - questo è il motivo perché gli sviluppatori di framework di test spendono così tanto sui loro messaggi di errore!)
Una volta superato il test dell'unità, devi rifattorizzare il codice di produzione sotto la protezione dei test. (Nota che in questo momento, il test di accettazione e il test funzionale stanno ancora fallendo, ma va bene, dal momento che stai solo rifattando le singole unità che sono coperte dai test unitari.)
Ora crei il prossimo test unitario e ripeti quanto sopra, finché non passa anche il test funzionale. Sotto la protezione del test funzionale, ora puoi effettuare il refactoring su più unità.
Questo ciclo intermedio ora si ripete fino a quando non passa il test di accettazione, a quel punto è ora possibile effettuare i refactoring su tutto il sistema.
Ora scegli il prossimo criterio di accettazione e il ciclo esterno ricomincia.
Kent Beck, lo "scopritore" di TDD (non gli piace il termine "inventore", dice che la gente lo ha sempre fatto, gli ha dato un nome e ha scritto un libro a riguardo) usa un'analogia dalla fotografia e chiama questo "zoom in e out".
Nota: non hai sempre bisogno di tre livelli di test. Forse, a volte hai bisogno di più. Più spesso, hai bisogno di meno. Se le tue funzionalità sono ridotte e i tuoi test funzionali sono veloci, puoi procedere senza (o con meno test unitari). Spesso, hai solo bisogno di test di accettazione e test unitari. Oppure i criteri di accettazione sono così dettagliati che i test di accettazione sono test funzionali.
Kent Beck dice che se ha un test funzionale veloce, piccolo e focalizzato, scriverà prima i test unitari, lascerà che i test unitari guidino il codice, quindi cancellino (alcuni) i test unitari che coprono il codice che è anche coperto dal test funzionale veloce. Ricorda: il codice di prova è anche il codice che deve essere mantenuto e refactored, meno c'è, meglio è!
However, I am wondering if the test-driven approach can also be applied to other forms of tests.
In realtà non applichi TDD ai test. Lo si applica all'intero processo di sviluppo. Questo è ciò che la parte "guidata" di Test- Driven -Sviluppo significa: tutto il tuo sviluppo è guidato da test. I test non solo guidano il codice che scrivi, ma anche il codice che per scrivere, quale codice scrivere dopo. Guidano il tuo design. Ti dicono quando hai finito. Ti dicono cosa lavorare dopo. Ti parlano dei difetti di progettazione nel tuo codice (quando i test sono difficili da scrivere).
Keith Braithwaite ha creato un esercizio che chiama TDD As If You Significa . Consiste in un insieme di regole (basate su Tre regole del TDD dello zio Bob Martin , ma molto più severe) che devi rigorosamente seguire e che sono progettati per orientarti verso l'applicazione di TDD in modo più rigoroso. Funziona al meglio con la programmazione di coppie (in modo che la tua coppia possa essere sicura che non infrangi le regole) e un istruttore.
Le regole sono:
- Write exactly one new test, the smallest test you can that seems to point in the direction of a solution
- See it fail; compilation failures count as failures
- Make the test from (1) pass by writing the least implementation code you can in the test method.
- Refactor to remove duplication, and otherwise as required to improve the design. Be strict about using these moves:
-
you want a new method—wait until refactoring time, then … create new (non-test) methods by doing one of these, and in no other way:
- preferred: do Extract Method on implementation code created as per (3) to create a new method in the test class, or
- if you must: move implementation code as per (3) into an existing implementation method
-
you want a new class—wait until refactoring time, then … create non-test classes to provide a destination for a Move Method and for no other reason
- populate implementation classes with methods by doing Move Method, and no other way
Queste regole sono pensate per esercitare TDD. Non sono pensati per fare effettivamente TDD in produzione (anche se nulla ti impedisce di provarlo). Possono sentirsi frustrati perché a volte sembrerà come se avessi fatto migliaia di piccoli piccoli passi senza fare veri progressi.