TDD vs. git bisect

1

Una regola empirica con git è, non effettuare commit dove il progetto non viene compilato o i test non passano. Tutti i commit dovrebbero costruire. Quindi, quando scopri un problema che non era stato precedentemente rilevato dai test, puoi utilizzare git bisect per scoprire dove è stato introdotto rapidamente. Se stai facendo bisecando per qualche problema particolare, e ti imbattono in commit che non si costruiscono, o i test falliscono per ragioni non correlate, può essere davvero fastidioso e richiedere molto tempo per capire come procedere con il bisect.

Tuttavia, TDD dice che quando eseguo lavori di sviluppo su una nuova funzione, dovrei iniziare scrivendo i test per la nuova funzione che non passano ancora. (Scopri cosa dovrebbe fare la funzione, quindi vai a farlo.)

Recentemente ho avuto una situazione in cui ho sviluppato un nuovo codice per il progetto A, che ha superato i test interni. Tuttavia, prima di unire il ramo di sviluppo, ho deciso di testare le dipendenze downstream B e C. La nuova versione di A ha rotto quelle build, quindi ora devo tornare indietro e correggere il ramo A di sviluppo.

La prima cosa che voglio fare è ridurre il codice fallito da B e C per testare i casi che si impegneranno ad A e diventare i miei nuovi test per la prossima iterazione di sviluppo.

Tuttavia, potrebbe essere relativamente facile creare i nuovi test, ma relativamente difficile da risolvere il nuovo problema. Non mi piace lasciare il lavoro non impegnato nel mio albero per molto tempo, soprattutto se si tratta di cose preziose come nuovi test. Ad esempio, cosa succede se inizio a lavorare su una nuova macchina o condivido i progressi con un collaboratore. Ma se eseguo il commit dei nuovi test, ho creato un commit errato in cui la build è stata interrotta.

Esistono buone tecniche o pratiche consolidate per conciliare queste preoccupazioni? Ecco alcune cose a cui ho pensato:

  1. Quando i nuovi test sono pronti, impegnali come al solito ma fai qualche tipo di nota nel messaggio di commit "nota: i nuovi test hanno intenzionalmente rotto la build". Quando git bisecting, se raggiungi tale commit, esegui immediatamente git checkout HEAD^ , e prova invece di eseguire il commit per provare a fare progressi nella bisettrice (Ripeti se il commit ha anche una tale nota.) Se il commit genitore è sbagliato, quindi git bisect non ti riporterà ai nuovi test commit, dal momento che sta cercando il primo commit errato. Se il commit genitore è buono, e git bisect ti riporta ai nuovi test commit, allora dovresti contrassegnarlo arbitrariamente come buono, perché il codice non è cambiato lì, solo i nuovi test sono stati aggiunti, quindi non può logicamente sii il primo cattivo commit in merito a qualunque problema tu stia effettivamente testando.

  2. Quando i nuovi test sono pronti, eseguili su un ramo new-tests . Quindi lavora sulla funzione rispetto al ramo develop . Potrebbero esserci più develop rami fuori da new-tests se ci sono più approcci in competizione. Se i test devono essere modificati, modificali e rebase sviluppa rami contro new-tests . Alla fine quando tutto sta passando, schiaccia tutto in un unico commit con i nuovi test e le nuove funzionalità di lavoro, completando il ciclo TDD ma anche senza commettere dead commit che finiscono su master .

  3. Il progetto dovrebbe effettivamente costruire due file eseguibili di test: test "obbligatori" e test "desiderati". In CI, entrambi i file eseguibili sono compilati ma i test "desiderati" possono fallire senza che la build venga contrassegnata come fallita. Quando vengono creati nuovi test, vengono inseriti nell'obiettivo "desiderato". Quando la funzione è terminata e i test desiderati stanno passando, vengono trasferiti su richiesto. L'unico problema con questo è, che cosa succede se i nuovi test non vengono ancora compilati. I test desiderati non saranno nemmeno compilati come parte di CI? C'è anche qualche punto per avere un target di test "desiderato"?

posta Chris Beck 25.07.2017 - 23:25
fonte

2 risposte

8

TDD dice di scrivere un test fallito, quindi di eseguire quel uno test pass, quindi facoltativamente refactor, quindi ripeti. Quel ciclo di solito richiede non più di pochi minuti e non dovresti aver bisogno di impegnarti nel mezzo. Se stai scrivendo tutti i tuoi test, poi scrivi tutto il tuo codice, non è TDD, è qualcosa di molto più difficile e meno utile.

    
risposta data 26.07.2017 - 00:08
fonte
4

Penso che la tua premessa non sia corretta.

A rule of thumb with git is, don't make commits where the project doesn't compile or the tests don't pass.

Non penso che questo sia vero affatto. Non dovresti aver paura di eseguire commit in GIT e persino di inviarli al telecomando per la collaborazione. dovresti tuttavia avere un ramo stabile che dovrebbe sempre essere compilato in modo pulito e superare tutti i test. Per te questo è il ramo develop . Non dovresti inviare test non funzionanti al ramo develop .

Quindi IMO # 2 è l'approccio corretto. Invece di nominare il ramo della funzione new-tests , assegnagli un nome significativo per la funzione per cui hai scritto i test. Puoi spingere i test su questo ramo, il tuo collega può contribuire all'implementazione in modo che i test passino. Una volta che tutti i test passano e il ramo è pronto, puoi rebase e schiacciare i commit (se lo desideri) all'ultimo develop e l'unione rapida in develop .

    
risposta data 25.07.2017 - 23:38
fonte

Leggi altre domande sui tag