Alternativa all'indicatore "Passing / Broken build"?

14

Quando si ha un'integrazione continua che esegue i test ad ogni commit, una best practice comune è far passare tutti i test in ogni momento (ovvero "non interrompere la compilazione").

Ho riscontrato alcuni problemi con questo:

Ad esempio, non è possibile aiutare un progetto open source creando test corrispondenti ai ticket. So che se propongo una richiesta di pull a un progetto open source contenente un test non riuscito, la compilazione verrà contrassegnata come non riuscita e il progetto non lo vorrà unito al suo repository perché "interrompe la compilazione".

E Non credo che sia una brutta cosa avere test falliti nel tuo repository , è come avere problemi aperti nel tuo tracker. Queste sono solo cose che devono essere risolte.

Lo stesso vale per un'azienda. Se lavori con TDD, non puoi scrivere test, eseguire il commit e quindi scrivere il codice logico che soddisfa il test. Ciò significa che se ho scritto 4-5 test sul mio portatile, non posso impegnarli prima di andare in vacanza. Nessuno può riprendere il mio lavoro. Non riesco nemmeno a "condividerli" con un collega se non mandandoli via e-mail per esempio. Inoltre impedisce di lavorare con una persona che scrive i test, l'altra sta scrivendo il modello.

Tutto ciò per dire, sto abusando / fraintendendo il processo di costruzione / integrazione continua? Mi sembra che "passare" / "non passare" sia un indicatore troppo stretto.

C'è un modo per rendere l'integrazione continua e TDD compatibili?

Forse esiste una soluzione / pratica standard per distinguere tra "nuovi test" (che possono fallire) e "test di regressione" (che dovrebbero non fallire perché erano abituati a lavorare)?

    
posta Matthieu Napoli 08.02.2013 - 14:49
fonte

8 risposte

12

Vedo dove stai arrivando, ma questi tipi di problemi sono in genere risolti in altri modi. C'è una buona ragione per cui questo è un protocollo standard. Se qualcuno invia un codice che non viene compilato, chiunque aggiorna il proprio codice avrà un programma che non viene compilato . Ciò include i programmatori che stanno attualmente lavorando su qualcosa di completamente diverso e in qualche modo si trovano in una situazione in cui devono aspettare prima di poter compilare e testare su cosa stanno lavorando.

Il protocollo standard è che puoi commettere modifiche anche per lavori completi o addirittura incompleti, finché compila in modo che i programmatori possano aggiornare il loro codice ogni giorno, se necessario.

Tuttavia, vedo ancora cosa stai ricevendo. A volte vuoi impegnarti per semplicemente salvare il tuo codice. Per questo, la maggior parte dei repository di sorgenti supporta la ramificazione. Questo ti permette di creare un ramo privato, lavorarci sopra senza disturbare gli altri, quindi unire il tronco quando il lavoro è completato. Ciò consente di eseguire il commit quando lo si desidera senza il backlash associato alla causa della rottura del build.

Se non è adatto, GIT ti permette di impegnare (spingendo) gli archivi sul tuo computer locale, ma probabilmente il repository potrebbe essere ovunque. È possibile creare un repository per lavoro potenzialmente parziale / incompleto e un altro repository per il lavoro finito e su quel repository è possibile aggiungere una build notturna.

Ancora una volta, non posso sottolineare abbastanza l'importanza. Non impegnare mai il codice rotto nel trunk! I tuoi contributi non possono influire sul lavoro di altri programmatori.

Modifica

Vedo che intendevi test non funzionanti, ma a mio modesto parere, c'è poca differenza. L'intero punto di un test è determinare se un particolare aspetto di un programma passa o fallisce. Se fallisce sempre e non fai niente, allora il test, nell'uso tradizionale dei test unitari, non serve a nulla. Se lo usi per eseguire altre metriche che non implicano necessariamente un commit "fallito" se uno di questi test fallisce, ti consiglio vivamente di trovare un altro modo per fare la stessa cosa.

Altrimenti rischi che il test non venga mai preso in considerazione o che causi il fallimento della tua build, che i tuoi colleghi programmatori ignorino le build fallite. È più importante che i programmatori realizzino quando hanno rotto una build piuttosto che eseguire un test che non offre una visione reale e può portare solo a cattive pratiche.

    
risposta data 08.02.2013 - 15:00
fonte
4

Dato un ramo master con test falliti, come puoi essere sicuro - senza confrontare l'elenco con quelli precedenti - che non hai introdotto bug?

Il semplice rilevamento del numero di test non riusciti è insufficiente: potresti correggere un test e romperne un altro. E se sei in vacanza, non sarà chiaro agli altri che guardano alla build fallita.

Mantieni sempre pulito e verde il tuo ramo principale . Lavora in una filiale. Mantieni il ramo sotto CI, in un lavoro separato, e hai test falliti per il contenuto del tuo cuore. Basta non spezzare il padrone.

Chiedi al revisore della filiale di unire il tuo ramo solo se supera tutti i test. (Più strong: fai in modo che il revisore sia in grado di unire il tuo ramo se il risultato dell'unione del ramo in master supera tutti i test!)

    
risposta data 08.02.2013 - 16:00
fonte
2

Ci sono modi per risolvere i tuoi problemi senza buttar via le pratiche ben comprese e accettate sull'integrazione continua.

Inizierò con il problema di eseguire un "test non funzionante" che corrisponde a un ticket. Una soluzione è quella di creare uno o più test di interruzione che espongono il problema, quindi in realtà risolvere il problema , in modo che possano essere uniti insieme alla riga di codice principale. La seconda soluzione è quella di avere i test non funzionanti, ma usare qualche tipo di ignore flag in modo che non vengano effettivamente eseguiti e interrotti la build. Eventualmente aggiungi un commento o un'annotazione speciale che rende molto evidente che si tratta di un test non funzionante per Ticket#N . Allega anche una nota al ticket stesso che fa riferimento ai test creati che sono in attesa di essere non firmati ed eseguiti. Ciò aiuterebbe una persona a fissare il biglietto, ma non sarebbe anche una bandiera rossa per qualcuno che incontra il test.

E sul tuo prossimo problema con TDD. TDD riguarda la scrittura di un piccolo test e quindi la scrittura di una piccola porzione di codice per eseguire il test . Quindi continua a ripetere finché non hai un piccolo modulo funzionale. Sento che se scrivi 4-5 test, poi vai in vacanza, potresti sbagliare. Puoi accoppiare il programma con qualcuno in modo che uno di voi scriva il test, l'altro il codice corrispondente. Non dovresti tuttavia utilizzare il repository di codice principale per condividere questo codice tra voi due prima che un modulo completato sia pronto per essere eseguito il commit. Come altri hanno suggerito, un ramo condiviso risolverebbe i tuoi problemi lì.

Cercare di rompere il mantra dell'integrazione continua può portare a percorsi inaspettati e spaventosi. Ad esempio, cosa significherebbe la copertura del codice in questo tipo di ambiente ? In che modo gli sviluppatori non ritengono che il sistema abbia molti " Windows rotto " ? Come si può fare un cambiamento, eseguire il test e sapere se stanno effettivamente rompendo qualcosa di nuovo, o sono solo le vecchie cose?

    
risposta data 09.02.2013 - 03:45
fonte
1

Penso che il tuo problema fondamentale sia che includi i RISULTATI del test come parte della build. Mentre ovviamente alcune persone sono d'accordo con te, altre no. La rottura della build si verifica quando non si crea. Non quando non crea senza errori.

Considera un progetto importante come Windows o Linux, o anche qualcosa come Firefox - pensi che vengano spediti senza bug? Ovviamente no. Ora questi progetti non stanno facendo TDD, ma questo è davvero irrilevante - TDD non cambia due fatti fondamentali: esistono degli errori e ci vuole tempo per risolverli. Tempo in cui un progetto (open source o meno) non può permettersi di sprecare i bug a bassa priorità. Di recente KDE ha corretto un errore di oltre un decennio. Quando è stata l'ultima volta che hai sentito qualcuno dire "Sono contento che abbiamo aspettato un decennio per spedire il nostro progetto"?

TDD, in un certo senso, probabilmente rende più facile spedire con bug - perché hai una migliore comprensione di quale sia il difetto. Se è possibile definire con precisione ciò che causa l'errore, si dispone di una base eccellente per valutare il costo di fissarlo.

Il mio consiglio è quello di trovare un progetto che non dispiaccia alcuno rosso tra il verde.

    
risposta data 09.02.2013 - 07:40
fonte
1
 > a common best practice is to have all the tests passing (green) at all times.

Preferisco avere tutti i test non in errore (non rosso)

Con questa definizione leggermente diversa puoi anche definire test che sono

  • non ancora implementato (grigio in nunit se c'è una NotImplementedException)
  • noto per essere fallito="ha bisogno di fare" segnando / annotando il test come ignorato (giallo)

Se li controlli nel repository, la tua build continua non è rotta e quindi valida.

    
risposta data 09.02.2013 - 12:34
fonte
0

Potresti prendere in considerazione due "concetti" di configurazione CI diversi.

  1. Generazioni di elementi di configurazione regolari. La build CI normale deve compilare ed eseguire solo quei test per cui è stato scritto il codice per farli passare, in modo che i report CI di test pass / fail siano un chiaro indicatore non ambiguo di regressione rispetto allo stato precedentemente accettato del codice.
  2. Una build CI "futura". Questa build compila ed esegue solo quei test per i quali non è stato scritto alcun codice specifico per farli passare. Ci possono essere diversi motivi per avere un test del genere:

    • I test possono essere aggiunti per casi di errore specifici dal tracker dei problemi, per il quale non è stata ancora tentata alcuna correzione. È chiaramente utile avere già un test in esecuzione codificato per un problema anche senza una correzione.

    • Test aggiunti per nuove funzionalità richieste che non sono ancora state implementate.

    • Spesso è più facile sapere come testare un malfunzionamento o una funzionalità piuttosto che sapere come implementare la funzionalità o la correzione e separare i due passaggi commettendo il test sul controllo del codice sorgente può essere utile per garantire che nessuna informazione venga persa .

Come nell'IC "standard", nel normale regime di sviluppo il team guarderebbe solo ai risultati di build giornalieri della build regolare.

Il team può anche tenere d'occhio l'evoluzione dei casi di test dalla build futura del CI, in particolare per vedere se eventuali modifiche apportate all'IC regolare risolvono effettivamente i problemi della build "futura", che può essere un'indicazione di un importante problema di fondo o miglioramento del design.

Infine, se un membro del team ha più tempo a disposizione, può dare un'occhiata a risolvere uno dei problemi da "futuro", e se riesce a migrarlo a "normale" (aggiornando lo stato del tracker del problema).

    
risposta data 08.02.2013 - 17:29
fonte
0

And I don't believe it is a bad thing to have failing tests in your repo, it's like having open issues in your tracker. These are just things waiting to be fixed.

Il problema non sta fallendo i test, è un semplice indicatore del contesto di regressione. Aka: come sviluppatore, posso controllare un singolo indicatore e sapere se ho introdotto una regressione o codice di rottura.

Nel momento in cui introduci il concetto di errori "soft" (è ok, ci stiamo lavorando / non è ancora implementato / stiamo aspettando la nuova versione / passerà di nuovo una volta che questa build sarà stata riparata) , hai bisogno di tutti quelli che potrebbero correre o guardare il test per conoscere lo stato previsto. Che in una squadra abbastanza numerosa cambierà di ora in ora: il tuo indicatore diventa privo di significato. In un contesto più ristretto (test di integrazione privata del team, ad esempio), quindi penso che sia come un debito tecnico ed è ok - ha solo bisogno di essere gestito.

Il modo in cui la maggior parte degli indirizzi degli strumenti è "verde / che passa" riflette il risultato previsto - non che il codice funzioni:

  • Il fitness ha il concetto di fallimento previsto.
  • JUnit ha @Ignored / @Test (expect =)
  • Cucumber ha lo stato 'non ancora implementato' (o come si chiama)

Quelli hanno i loro problemi (come fai a distinguere tra "sì, sappiamo che è rotto, lavorarci su" e "il comportamento corretto è un'eccezione") - ma aiutano.

    
risposta data 09.02.2013 - 17:26
fonte
0

Uso i test saltati.

Nel particolare framework di test dell'unità che utilizzo, posso sollevare un'eccezione SkipTest. Il test non viene effettivamente eseguito e il suo errore non interromperà la build. Tuttavia, posso vedere il numero di test saltati e vedere se c'è del lavoro da fare in quell'area.

    
risposta data 21.02.2013 - 01:57
fonte

Leggi altre domande sui tag