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:
-
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. -
Quando i nuovi test sono pronti, eseguili su un ramo
new-tests
. Quindi lavora sulla funzione rispetto al ramodevelop
. Potrebbero esserci piùdevelop
rami fuori danew-tests
se ci sono più approcci in competizione. Se i test devono essere modificati, modificali erebase
sviluppa rami contronew-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 sumaster
. -
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"?