I test per lo sviluppo test-driven (TDD) sono sempre unit-test?

40

Comprendo lo sviluppo basato sui test fino a quando è consentito solo scrivere codice produttivo quando si ha un test unitario (rosso) in errore. Sulla base di questo ho la domanda se l'approccio basato sui test può essere applicato anche ad altre forme di test.

    
posta user1364368 08.06.2017 - 11:02
fonte

8 risposte

28

Tutti i TDD richiedono che tu scriva un test non funzionante, quindi modifica il codice per farlo passare.

In genere, i "test unitari" sono piccoli e veloci e testano parte del codice in isolamento. Poiché sono veloci, rendono veloce anche il loop rosso / verde / refactor. Tuttavia, soffrono solo delle parti di test isolate. Quindi sono necessari anche altri test (integrazione, accettazione, ecc.). È comunque buona pratica seguire gli stessi principi: scrivere un test non funzionante, quindi modificare il codice per farlo funzionare. Basta essere consapevoli del fatto che sono in genere più lenti, quindi possono influire sul tempo di ciclo rosso / verde / refactor.

    
risposta data 08.06.2017 - 11:53
fonte
60

Il ciclo red refactor verde è basato su un principio molto valido:

considera solo i test che hai visto sia passati che falliti

Sì, funziona anche con test di integrazione automatici. Anche test manuali Diamine, funziona con i tester delle batterie per auto. Ecco come si prova il test.

Alcuni pensano che i test unitari coprano la più piccola cosa che può essere testata. Alcuni pensano a tutto ciò che è veloce da testare. Il TDD è molto più del semplice ciclo refact red green, ma quella parte ha un insieme di test molto specifico: non sono i test che idealmente userete una volta prima di inviare una serie di modifiche. Sono i test che eseguirai ogni volta che cambierai. Per me, quelli sono i tuoi test unitari.

    
risposta data 08.06.2017 - 11:27
fonte
12

However, I am wondering if the test-driven approach can also be applied to other forms of tests.

Sì, e un approccio ben noto che fa questo è Sviluppo basato sul comportamento . I test generati dalle specifiche formali in BDD potrebbero essere chiamati "unit test", ma in genere non saranno così di basso livello come nel TDD reale, probabilmente si adattano meglio al termine "test di accettazione".

    
risposta data 08.06.2017 - 12:51
fonte
8

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:

  1. Write exactly one new test, the smallest test you can that seems to point in the direction of a solution
  2. See it fail; compilation failures count as failures
  3. Make the test from (1) pass by writing the least implementation code you can in the test method.
  4. Refactor to remove duplication, and otherwise as required to improve the design. Be strict about using these moves:
    1. 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
    2. 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
    3. 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.

    
risposta data 08.06.2017 - 12:54
fonte
2

TDD non è affatto limitato a ciò che la tradizionale comunità di Software Testing chiama "unit test". Questo malinteso molto comune è il risultato dello sfortunato sovraccarico di Kent Beck del termine "unità" nel descrivere la sua pratica del TDD. Ciò che intendeva per "unit test" era un test che si svolge in isolamento. Non dipende da altri test. Ogni test deve impostare lo stato di cui ha bisogno e fare qualsiasi pulizia quando è fatto. È in questo senso che un test unitario nel senso TDD è un'unità. È autonomo. Può essere eseguito da solo o può essere eseguito insieme a qualsiasi altro test di unità in qualsiasi ordine.

Riferimento : "Test Driven Development By Example", di Kent Beck

Kent Beck descrive cosa intende per "unit test" nel Capitolo 32 - Mastering TDD

    
risposta data 08.06.2017 - 20:08
fonte
1

Non ho letto libri su di esso, né seguo completamente il TDD "standard" tutto il tempo, ma nella mia mente il punto principale della filosofia TDD, che sono completamente d'accordo, è che devi definisci il successo per primo Questo è importante a tutti i livelli del design, da "Qual è l'obiettivo di questo progetto?" a "Quali dovrebbero essere gli input e gli output di questo piccolo metodo?"

Ci sono molti modi per fare questa definizione di successo. Uno utile, in particolare per quei metodi di basso livello con potenzialmente molti casi limite, è quello di scrivere test nel codice. Per alcuni livelli di astrazione, può essere utile solo scrivere una breve nota sull'obiettivo del modulo o qualsiasi altra cosa, o anche solo controllarti mentalmente (o chiedere a un collega) per assicurarsi che tutto abbia un senso e sia in luogo logico. A volte è utile descrivere un test di integrazione nel codice (e naturalmente questo aiuta a automatizzarlo), e talvolta è utile solo definire un piano di test rapido e ragionevole che puoi usare per assicurarti che tutti i sistemi stiano lavorando insieme nel modo in cui sono in attesa.

Ma a prescindere dalle tecniche o dagli strumenti specifici che stai usando, nella mia mente la cosa fondamentale da togliere alla filosofia TDD è che la definizione del successo avviene prima. Altrimenti, stai lanciando il dardo e dipingendo il bullseye ovunque sia successo.

    
risposta data 08.06.2017 - 16:54
fonte
1

Nel talk Test-Driven Development: questo non è quello che intendevamo Steve Freeman mostra la seguente diapositiva della grande immagine del TDD (vedere immagine sotto risposta). Questo include un passaggio "Scrivi un test end-to-end in errore" , seguito da "Scrivi un test unitario in errore". (Clicca per ingrandire, è in alto a destra)

Quindi no in TDD i test non sono sempre unit-test.

E sì, puoi (e forse dovresti) iniziare con un test end-to-end di livello superiore che fallisce prima di scrivere il tuo primo test unitario. Questo test descrive il comportamento che vuoi raggiungere. Ciò genera copertura su più livelli della piramide di prova . Adrian Sutton spiega l'esperienza di LMAX che mostra che i test end-to-end possono gioca un ruolo importante e prezioso .

    
risposta data 09.06.2017 - 11:10
fonte
-1

No, non può essere applicato ad altri tipi di test, per una semplice ragione pratica: altri tipi di test impiegano troppo tempo per essere eseguiti.

Tipico ciclo TDD è: scrittura fallita test, implementazione, codice refactoring. Le fasi intermedie sono la costruzione e l'esecuzione di test, e questi devono essere velocissimi. Se non lo sono, allora le persone inizieranno a saltare i passaggi, e quindi non stai più facendo TDD.

    
risposta data 09.06.2017 - 12:06
fonte

Leggi altre domande sui tag