TDD e controllo versione

21

Attualmente sto imparando a conoscere TDD e sto cercando di metterlo in pratica nei miei progetti personali. Ho anche utilizzato il controllo della versione ampiamente su molti di questi progetti. Sono interessato all'interazione di questi due strumenti in un tipico flusso di lavoro, specialmente quando si tratta della massima per mantenere piccoli i commit. Ecco alcuni esempi che ti vengono in mente:

  1. Inizio un nuovo progetto e scrivo un semplice test per creare una classe ancora inesistente. Devo eseguire il test prima di scrivere la classe anche se il test non viene compilato? O dovrei eliminare la quantità minima di codice necessaria per compilare il test prima di eseguire il commit?

  2. Trovo un bug e scrivo un test per ricrearlo. Devo eseguire il test fallito o implementare la correzione dei bug e poi eseguire il commit?

Questi sono i due esempi che vengono subito in mente. Sentiti libero di fornire esempi aggiuntivi nella risposta.

Modifica

Ho fatto un'ipotesi in entrambi gli esempi che subito dopo aver scritto il test scriverò il codice per far passare il test. Potrebbe anche presentarsi un'altra situazione: lavoro su un progetto usando TDD per diverse ore senza impegnarmi. Quando finalmente faccio i commit, voglio spezzare il mio lavoro in piccoli pezzi. (Git rende questo relativamente facile anche se vuoi voler commettere solo alcune delle modifiche in un singolo file.)

Ciò significa che la mia domanda riguarda tanto quanto da impegnare quanto lo è per quando per il commit.

    
posta Code-Guru 16.06.2013 - 21:15
fonte

6 risposte

19

Should I commit the test before writing the class even though the test doesn't even compile? Or should I stub out the minimum amount of code that is needed to get the test to compile before committing?

Certo che no. Dovresti finire sia il test che la lezione. L'invio di qualcosa 1 che non viene nemmeno compilato non ha senso e renderà sicuramente le persone che lavorano sullo stesso progetto arrabbiate se lo fai regolarmente.

I find a bug and write a test to recreate it. Should I commit the failing test or implement the bug fix and then commit?

No, non eseguire il test fallito. La legge di LeBlanc afferma:

Later equals never.

e il tuo test potrebbe fallire per un lungo periodo. È meglio correggere il problema non appena viene rilevato.

Inoltre, lo stile di sviluppo TDD dice:

Test-driven development constantly repeats the steps of adding test cases that fail, passing them, and refactoring.

Se esegui il check in un test fallito, significa che non hai completato il ciclo.

1 Quando ho detto commit, intendevo davvero impegnarmi nel trunk (per gli utenti git, spingere le modifiche, in modo che gli altri sviluppatori possano ottenerle).

    
risposta data 16.06.2013 - 21:26
fonte
6

Should I commit the test before writing the class even though the test doesn't even compile?

No.

Should I commit the failing test

No.

Qui stai parlando di due paradigmi:

  1. sviluppo basato su test - che non dice nulla sull'impegno del codice. In effetti, ti dice su come scrivere il codice e quando hai finito. Quindi considererei ogni 'fatto' come candidato per un commit.
  2. sviluppo agile, in particolare: "commit early and often" (che non richiede TDD). L'idea alla base è quella di avere una rapida integrazione con altri componenti nel sistema e ottenere così un feedback tempestivo. Se si esegue il commit in un DVCS localmente e non si preme, non ha alcun valore in questo senso. I commit locali aiutano solo gli sviluppatori a strutturare il loro lavoro.

La mia raccomandazione è: segui il cerchio di TDD fino a quando il tuo codice non viene compilato, i tuoi test sono verdi e hai qualcosa da contribuire al sistema. Pertanto dovresti tagliare le tue caratteristiche verticalmente, ad es. per una nuova maschera di interfaccia utente non creare l'intero modulo e commettere senza la logica di business, ma piuttosto implementare un aspetto minuscolo, ma nel frontend e nella logica di business anche nel livello di persistenza.

Per un bugfix di grandi dimensioni, esegui il commit dopo ogni miglioramento (ad esempio, il refactoring), anche se il bug non è stato ancora risolto. I test dovrebbero essere verdi e il codice deve essere compilato, tuttavia.

    
risposta data 17.06.2013 - 10:43
fonte
5

Certo, inizi con l'uso di un sano controllo del codice sorgente come git.

Quindi puoi lavorare nel modo che preferisci e impegnarti in ogni angolo: qualsiasi passo o sottofase è un gioco leale.

Quindi, prima di spingere la roba, si schiaccia l'intero lavoro in un singolo commit. O una coppia, in punti in cui tutto è verde e la composizione ha un senso. E spingere quei commetti sensati. Per il caso multiplo, crea un ramo che si fonde con --no-ff.

Il controllo del codice sorgente non è un sistema di tracciamento del lavoro o uno storico. I commit devono presentare un delta coerente sensibile, mentre lo stato di checkout deve essere compilato almeno. Gli intermedi possono essere conservati per un po 'a scopo di revisione, ma una volta che tutto è considerato ok, un singolo commit per caratteristica è giusto.

    
risposta data 17.06.2013 - 01:54
fonte
5

Should I commit the test before writing the class even though the test doesn't even compile?

Con un SCM ramificato (ho visto che usi Git) dovresti eseguire il commit ogni volta che vuoi un punto di backup ("Ho rovinato qualcosa, resetterò la directory di lavoro all'ultimo punto di backup") o quando hai una versione stabile . Quando hai una versione stabile (tutti i test passano), dovresti anche considerare di unire il ramo di funzione corrente al tuo ramo di sviluppo principale.

Or should I stub out the minimum amount of code that is needed to get the test to compile before committing?

Fino a te (git ti dà la flessibilità di impegnarti in qualsiasi momento, senza intaccare altri membri del tuo team o la tua capacità di lavorare su caratteristiche diverse). Assicurati di non avere più funzioni incomplete (non funzionanti) nello stesso ramo nello stesso momento (quindi si bloccheranno a vicenda).

I find a bug and write a test to recreate it. Should I commit the failing test or implement the bug fix and then commit?

Di solito faccio due commit per questo, a meno che il codice di test sia veramente piccolo / banale da scrivere.

These are the two examples that come immediately to mind. Feel free to provide additional examples in your answer.

Edit:

I made an assumption in both examples that I immediately after writing the test I will write code to make the test pass.

Potrebbe essere un'ipotesi errata da fare. Se lavori da solo (progetto personale) nulla ti impedisce di farlo sempre. In uno dei miei progetti di maggior successo (per quanto riguarda il mantenimento di alta qualità del codice e TDD durante lo sviluppo del progetto) abbiamo definito i test a volte settimane prima di implementarli (ad esempio, diciamo "il test_FOO_with_null_first_parameter" è ora definito come una funzione vuota e lo faremo in quel modo). A volte ci vorrebbe uno sprint (o mezzo sprint) a volte un mese circa, per aumentare la copertura del test per il modulo, dal momento che avevamo già dichiarato che era facile stimare.

Another situation might also arise: I work on a project using TDD for several hours without committing. When I finally make commits, I want to break up my work into small chunks. (Git makes this relatively easy even if you want to want to commit only some of the changes in a single file.) This means that my question is as much about as what to commit as it is about when to commit.

Direi sicuramente impegnarsi a creare punti di backup . Questo funziona molto bene per i test di esplorazione ("aggiungerò solo alcune stampe su base di codice, eseguito e git reset --hard per rimuoverle quando ho finito) e per la prototipazione.

    
risposta data 17.06.2013 - 12:09
fonte
4

È mia comprensione del mondo che ci si impegna a segnare un punto sul quale potrebbe essere auspicabile il ritorno. Il punto a cui un test fallisce (ma compila) è sicuramente uno di questi punti. Se dovessi vagare nella direzione sbagliata cercando di fare un test pass, vorrei poter ripristinare il codice al punto di partenza e riprovare; Non posso farlo se non ho eseguito il commit.

    
risposta data 17.06.2013 - 11:20
fonte
2

Nel mio flusso di lavoro, quando possibile, lavoro incerto su un ramo personale di controllo del codice sorgente. Quindi posso provare, fallire, riprovare se necessario fino a quando non funziona, e impegnarmi solo nel progetto più grande quando ho un codice di lavoro effettivo.

Da una prospettiva TDD, la domanda "prima fai il check-in?" dipende interamente dal codice su cui stai lavorando. Se è un nuovo codice, non esegui il check-in finché non hai qualcosa che valga la pena di effettuare il check-in. Ma se si trova un errore nel codice già compilato o spedito, è consigliabile effettuare il check-in di un test per riprodurre il problema, DA SE STESSO, soprattutto se è la fine di una giornata lavorativa e se ne andrà dall'ufficio prima di risolvere il problema il codice.

(Naturalmente, se il tuo negozio ha un processo di build automatizzato che muore se qualche unit test fallisce, potresti non voler controllare un test fallito fino a quando non correggi il bug, ma sembra un modo strano di lavorare, poiché "trova e documenta bug" e "risolvi bug" può essere fatto da due team completamente diversi.)

    
risposta data 16.06.2013 - 23:45
fonte

Leggi altre domande sui tag