Come eseguire lo sviluppo Test Driven

15

Ho solo 2 anni di esperienza nello sviluppo di applicazioni. In quei due anni il mio approccio allo sviluppo era il seguente

  1. Analizza i requisiti
  2. Identity Core component / Objects, funzioni richieste, comportamento, processo e relativi vincoli
  3. Crea classi, relazione tra loro, vincoli sul comportamento degli oggetti e amp; afferma
  4. Crea funzioni, elabora con vincoli comportamentali secondo i requisiti
  5. Prova l'applicazione manualmente
  6. Se il requisito cambia, modifica componente / funzioni, quindi prova manualmente l'applicazione

Recentemente sono stato introdotto a TDD e ritengo che questo sia un ottimo modo per fare sviluppo in quanto il codice sviluppato ha forti ragioni per esistere e molti dei problemi di post-distribuzione sono mitigati.

Ma il mio problema è che non sono in grado di creare prima i test, piuttosto sto identificando i componenti e sto solo testandoli per scrivere prima di scrivere effettivamente i componenti. la mia domanda è

  1. Sto facendo è giusto? Se non è esattamente quello che devo cambiare
  2. Esiste un modo per identificare se il test che hai scritto sia sufficiente?
  3. È buona pratica scrivere un test per funzionalità molto semplici che potrebbero essere equivalenti a 1 + 1 = 2 o è solo un overplay?
  4. È opportuno cambiare funzionalità e quindi verificare se i requisiti cambiano?
posta Yogesh 16.11.2014 - 14:03
fonte

4 risposte

19

Am I doing it is right? If not what exactly I have to change

È difficile dire solo da questa breve descrizione, ma sospetto che, no, tu sia non che lo fa bene. Nota: non sto dicendo che quello che stai facendo non funziona o è in qualche modo cattivo, ma non stai facendo TDD. La "D" centrale significa "Driven", i test guidano tutto, il processo di sviluppo, il codice, il design, l'architettura, tutto .

I test ti dicono cosa scrivere, quando scriverlo, cosa scrivere dopo, quando smettere di scrivere. Ti dicono il design e l'architettura. (Il design e l'architettura emergono dal codice attraverso il refactoring.) TDD non tratta di test. Non si tratta nemmeno di scrivere i test: TDD significa lasciare che i test ti guidino, scriverli prima è solo un prerequisito necessario per questo.

Non importa se in realtà scrivi il codice in basso, o se è completamente aggiornato: stai scrivendo (scheletri di) codice nella tua testa, quindi scrivendo i test per quel codice. Questo non è TDD.

L'abbandono di quell'abitudine è difficile . Davvero, davvero difficile. Sembra essere particolarmente difficile per i programmatori esperti.

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

Tipicamente, questo porterà a disegni molto diversi rispetto al "metodo pseudo-TDD" spesso praticato di "immaginare nella tua testa quale dovrebbe essere il design, quindi scrivere test per forzare quel progetto, implementare il design che avevi già immaginato prima di scrivere i tuoi test ".

Quando un gruppo di persone implementa qualcosa come un tic tac toe game usando pseudo-TDD, in genere finiscono con disegni molto simili che coinvolgono una sorta di classe Board con un array 3 × 3 di Integer s. E almeno una parte dei programmatori avrà effettivamente scritto questa lezione senza test perché "sanno che ne avranno bisogno" o "hanno bisogno di qualcosa per scrivere i loro test contro". Tuttavia, quando costringi lo stesso gruppo a applicare TDD come se lo intendessi, spesso finiscono con un'ampia varietà di design molto diversi, spesso non utilizzando nulla di simile a un Board .

Is there any way you can identify whether test you have written are enough?

Quando coprono tutti i requisiti aziendali. I test sono una codifica dei requisiti di sistema.

Is it good practice to writing test for very simple functionality which might be equivalent to 1+1 = 2 or is it just an overplay?

Di nuovo, lo hai indietro: non scrivi test per la funzionalità. Scrivi funzionalità per i test. Se la funzionalità per far passare il test risulta essere banale, è grandioso! Hai appena soddisfatto un requisito di sistema e non hai nemmeno dovuto lavorare duro per questo!

Is it good to change functionality and accordingly test if requirement changes?

No. Viceversa. Se un requisito cambia, cambi il test che corrisponde a quel requisito, guardalo fallire, quindi cambia codice per farlo passare. I test always vengono prima.

È difficile farlo. Hai bisogno di dozzine, forse centinaia di ore di pratica deliberata per costruire una sorta di "memoria muscolare" per arrivare a un punto, dove quando la scadenza incombe e sei sotto pressione, non lo fai Devo anche pensarci, e farlo diventa il più veloce e il modo più naturale per lavorare.

    
risposta data 17.11.2014 - 11:26
fonte
5

Descrivi il tuo approccio allo sviluppo come un processo "top-down-only" - parti da un livello di astrazione più alto e vai sempre più nei dettagli. Il TDD, almeno nella forma in cui è popolare, è una tecnica "dal basso verso l'alto". E per qualcuno che lavora per lo più "dall'alto verso il basso" può essere davvero molto insolito lavorare "dal basso verso l'alto".

Quindi, come puoi portare più "TDD" nel tuo processo di sviluppo? Innanzitutto, suppongo che il tuo processo di sviluppo non sia sempre così "top-down" come lo hai descritto sopra. Dopo il passaggio 2, probabilmente avrai identificato alcuni componenti che sono indipendenti dagli altri componenti. A volte decidi di implementare questi componenti per primi. I dettagli dell'API pubblica di tali componenti probabilmente non seguono solo le tue esigenze, i dettagli seguono anche le tue decisioni di progettazione. Questo è il punto in cui è possibile iniziare con TDD: immagina come utilizzerai il componente e in che modo utilizzerai effettivamente l'API. E quando inizi a codificare un tale utilizzo dell'API sotto forma di test, hai appena iniziato con TDD.

In secondo luogo, puoi fare TDD anche quando stai per codificare più "top-down", iniziando con componenti che dipendono prima da altri componenti non esistenti. Quello che devi imparare è come "deridere" prima queste altre dipendenze. Ciò consentirà di creare e testare componenti di alto livello prima di passare ai componenti di livello inferiore. Un esempio molto dettagliato su come fare TDD in modo top-down può essere trovato in questo post sul blog di Ralf Westphal .

    
risposta data 16.11.2014 - 16:41
fonte
3

Am I doing it is right? If not what exactly I have to change

Stai andando bene.

Is there any way you can identify whether test you have written are enough?

Sì, utilizza uno strumento di test / codice . Martin Fowler offre alcuni buoni consigli sulla copertura del test.

Is it good practice to writing test for very simple functionality which might be equivalent to 1+1 = 2 or is it just an overplay?

In generale, qualsiasi funzione, metodo, componente ecc. che ci si aspetta di produrre qualche risultato dato che alcuni input sono un buon candidato per un test unitario. Tuttavia, come con la maggior parte delle cose nella vita (di ingegneria), devi considerare i tuoi compromessi: è il Sforzo compensato scrivendo il test unitario risultante in una base di codice più stabile nel lungo periodo? In generale, si consiglia di scrivere prima il codice di test per funzionalità cruciali / critiche. Più tardi, se trovi che ci sono dei bug associati a una parte non testata del codice, aggiungi altri test.

Is it good to change functionality and accordingly test if requirement changes?

Il vantaggio di avere test automatici è che vedrai immediatamente se una modifica interrompe le asserzioni precedenti. Se ci si aspetta questo a causa di requisiti modificati, sì, è ok cambiare il codice di test (infatti, nel TDD puro cambieresti prima i test in base ai requisiti, quindi adotti il codice finché non soddisfa i nuovi requisiti).

    
risposta data 16.11.2014 - 15:55
fonte
3

Scrivere prima i test è un approccio completamente diverso alla scrittura del software. I test non sono solo uno strumento di verifica della funzionalità del codice (tutti passano) ma la forza che definisce il design. Sebbene la copertura del test possa essere una metrica utile, non deve essere l'obiettivo in sé: l'obiettivo di TDD non è di ottenere una buona percentuale di copertura del codice, ma di pensare alla verificabilità del codice prima di scriverlo.

Se hai problemi con i test di scrittura, ti consiglio caldamente di fare una sessione di programmazione delle coppie con qualcuno che ha esperienza in TDD, in modo da avere una mano sull'esperienza del "modo di pensare" sull'intero approccio .

Un'altra buona cosa da fare è guardare video online in cui il software viene sviluppato utilizzando TDD sin dalla prima riga. Bene, quello che una volta mi presentavo a TDD era Giochiamo a TDD di James Shore. Date un'occhiata, illustrerà come funziona il design emergente, quali domande dovreste porvi mentre scrivete i test e come vengono create, reinterpretate e ripetute nuove classi e metodi.

Is there any way you can identify whether test you have written are enough?

Credo che questa sia la domanda sbagliata da porre. Quando fai TDD, hai scelto di fare TDD e design emergente come metodo per scrivere software. Se qualsiasi nuova funzionalità che devi aggiungere inizia sempre con un test, sarà sempre lì.

Is it good practice to writing test for very simple functionality which might be equivalent to 1+1 = 2 or is it just an overplay?

Ovviamente dipende, usa il tuo giudizio. Preferisco non scrivere test sui parametri null checks, se il metodo non fa parte dell'API pubblica, ma altrimenti, perché non dovresti confermare che il metodo Add (a, b) restituisce effettivamente un + b?

Is it good to change functionality and accordingly test if requirement changes?

Ancora una volta, quando modifichi o aggiungi nuove funzionalità al tuo codice, inizi con un test, sia che si aggiungano nuovi test sia che si modifichi uno esistente quando cambiano i requisiti.

    
risposta data 16.11.2014 - 22:47
fonte