Come mantenere stabile il bagagliaio quando i test richiedono molto tempo?


9

Abbiamo tre serie di test suite:

  • Una "piccola" suite, che richiede solo un paio d'ore per funzionare
  • Una suite "media" che richiede più ore, di solito viene eseguita ogni notte (di notte)
  • Una suite "grande" che richiede una settimana + per l'esecuzione

Abbiamo anche un sacco di suite di test più brevi, ma non mi sto concentrando su di esse qui.

La metodologia attuale consiste nell'eseguire la piccola suite prima di ogni commit sul trunk. Quindi, la suite di medie dimensioni viene eseguita ogni notte e, se la mattina si è rivelata fallita, proviamo a isolare quale degli impegni di ieri era la colpa, il rollback che commette e riprova i test. Un processo simile, solo con frequenza settimanale anziché notturna, viene eseguito per la suite di grandi dimensioni.

Sfortunatamente, la suite media fallisce abbastanza frequentemente. Ciò significa che il trunk è spesso instabile, il che è estremamente fastidioso quando si desidera apportare modifiche e testarle. È fastidioso perché quando esco dal bagagliaio, non posso sapere con certezza che è stabile e se un test fallisce non posso sapere con certezza se è colpa mia o no.

La mia domanda è: esiste una metodologia nota per gestire questo tipo di situazioni in un modo che lascerà il bagagliaio sempre in perfetta forma? ad es. "impegnarsi in uno speciale ramo di precommit che aggiornerà periodicamente il tronco ogni volta che passa di notte".

E importa se si tratta di un sistema centralizzato di controllo del codice sorgente come SVN o di un sistema distribuito come git?

A proposito, sono uno sviluppatore junior con una capacità limitata di cambiare le cose, sto solo cercando di capire se c'è un modo per gestire questo dolore che sto vivendo.


6
Non ho idea di quale software stiate lavorando, ma una piccola suite di test che richiede ore per essere eseguita è un po 'di WTF. Se funzionassero più velocemente, questo sarebbe più facile, non c'è modo di semplificare i test?
Benjamin Bannier,

2
cosa c'è di così "estremamente fastidioso" nel fatto che il trunk sia instabile? Non so se lo sai, ma una delle strategie di ramificazione più popolari è persino chiamata tronco instabile
moscerino del

1
Esistono molti modi per ottimizzare una suite di test (come per qualsiasi altro software). Non ho idea del perché il tuo impieghi così tanto tempo, ma potresti ad esempio essere in grado di riutilizzare un po 'dell'ambiente di test o semplicemente utilizzare algoritmi / strutture dati migliori durante l'esecuzione (la profilazione aiuta). Potrebbe anche essere che nessuno abbia avuto il tempo di identificare campioni rappresentativi e tu hai appena testato ogni possibile input / output rispetto a qualche riferimento. Forse il tuo buildsystem ti consente di codificare dipendenze di test del codice in modo da non dover eseguire il set completo. E so che questa non era la tua domanda, ecco perché l'ho fatta un commento, non una risposta.
Benjamin Bannier,

1
... hmm, la tua opzione migliore probabilmente migliorerà i test e la registrazione delle applicazioni in modo che sia più facile trovare il motivo dell'errore. In questo modo, bisognerebbe trovare e correggere la causa del fallimento invece di sprecare gli sforzi in "investigazioni investigative" alla ricerca di chi, quando e perché ha cambiato una particolare linea di codice ...
moscerino

1
@honk Alcuni test richiedono solo molto tempo per essere eseguiti. Lavoro per un'azienda che produce apparecchiature per l'acquisizione dei dati e il nostro test "parziale" dura circa un'ora. I test devono eseguire vari tipi di misurazioni e ciò richiede solo tempo.
Velociraptors il

Risposte:


1

L'unico modo per risolvere la causa principale dell'instabilità è disaccoppiare il codice in modo che le modifiche siano più isolate, come suggerito da altre risposte.

Tuttavia, come singolo sviluppatore, se desideri una build più stabile su cui lavorare personalmente, è relativamente facile da risolvere. Invece di lavorare fuori dalla punta, tiri solo l'ultima build che ha passato la suite di test durante la notte nel tuo albero di lavoro. Se è possibile creare rami di funzionalità per ogni modifica, quindi eseguire il ramo dell'ultima build stabile.

Sì, il tuo albero sarà indietro di qualche giorno, ma il più delle volte non importa. Fai il tuo lavoro contro la build stabile, quindi sai che le tue modifiche sono quelle che hanno superato tutti i test, quindi prima di effettuare il check-in, esegui l'aggiornamento alla versione più recente e fai la tua normale integrazione. Quindi dopo il check-in, eseguire nuovamente il backup dell'ultima build stabile.

Devi ancora fare il disordinato lavoro di integrazione, ma quello che mi piace di questo metodo è che isola il lavoro di integrazione in un momento più conveniente per me e mi dà una base di codice stabile per lo sviluppo quando non è conveniente. Ho un'idea molto migliore quando sono i miei cambiamenti che probabilmente hanno rotto la build contro quella di qualcun altro.


1
-1 lavorare dalle filiali è un'opzione praticabile, ma raccomandarlo senza suggerire di testare potrebbe fare più male che bene. Solo i test possono mostrare se è fattibile per un progetto specifico o meno. Ad esempio, in un progetto che ho fatto circa 2 anni fa, un simile test ha dimostrato che lavorare dalle filiali stava compiendo ~ 7 volte più sforzi rispetto al tronco instabile
moscerino del

Grazie Karl! Anche se questo non è ciò che speravo di imparare, si tratta di un approccio molto pratico che potrebbe aiutarmi a risolvere il problema in questione. E sono d'accordo che lavorare pochi giorni dietro il bagagliaio causerà raramente problemi di integrazione.
Quercia

12

So che stai cercando di evitarlo, ma la vera intuizione qui è rendersi conto che qualcosa è seriamente sbagliato con la tua base di codice: devi eseguire una suite completa di test che richiede una settimana solo per essere sicuro che il tuo codice sia stabile!

Il modo più vantaggioso per risolvere questo problema è iniziare a separare la base di codice e test in sottounità (indipendenti).
Ci sono enormi vantaggi in questo:

  • I test per ciascuna di queste unità verranno eseguiti più rapidamente (ce ne sono semplicemente meno) e non si interromperanno se qualcosa va storto in una delle unità indipendenti o a valle.
  • Un test fallito verrà individuato su una particolare unità che renderà molto più facile trovare la fonte del problema.
  • Puoi separare le posizioni VCS delle diverse unità in modo che il tuo ramo "stabile" possa essere un pick-n mix dell'ultima build testata con successo di ogni unità, in modo che una o due unità rotte non destabilizzino la tua versione "stabile" .

La gestione del rovescio della tua struttura VCS diventerà più complicata, ma a una settimana intera per il test completo, penso che tu possa sopportare il dolore!

Consiglio ancora di utilizzare una strategia di rami "stabile" e di "sviluppo" in un modo o nell'altro, ma ci sono molti modi per farlo e puoi scegliere quello che funziona meglio per la tua organizzazione (meta-repository con revisioni fisse che puntano a repository separati per ogni unità, un ramo stabile e un ramo dev, rami delle caratteristiche ....)


1
Non ho mai detto che il test di grandi dimensioni è un test atomico, è una suite di test . Quando un singolo sviluppatore apporta una modifica all'elemento X, esegue i test relativi a X, indipendentemente dalla suite di test da cui provengono. Questo è in aggiunta al test settimanale, che viene eseguito per assicurarsi che un cambiamento in un posto non abbia influito inaspettatamente su un altro posto. Ma fai notare che almeno separare le cose in questo modo contribuirà ad accelerare i test per moduli specifici, mantenendo il rischio all'incirca allo stesso livello.
Quercia

2
@oak - Beh, in un certo senso la suite È atomica se eseguendo tutto questo è l'unico modo in cui sei davvero sicuro che il codice sia stabile, ma fai un buon punto, quindi ho modificato la mia risposta.
Joris Timmermans,

4
Disponiamo di enormi testuite per i nostri compilatori, alcuni dei quali richiedono diversi giorni per essere eseguiti, e non penso che sia insolito per un software complesso come un compilatore C ++. Non è che la suite definisca ciò che deve essere considerato "stabile", ma piuttosto che ci sono milioni di diverse parti maiuscole della generazione del codice che è impossibile testarle tutti i giorni.
JesperE,

1
@JesperE - è comprensibile, se l'enorme suite di test non definisce "stabile" ma è un gigantesco test di sanità mentale. Non mi aspetto che la suite completa (o anche la suite media) fallisca molto spesso.
Joris Timmermans,

1

Per SVN, non conosco cose come "pre-commit". Penso che probabilmente produrrà commit e rollback quando il test fallisce. Come dice doc-brown, l'unico modo è quello di impegnarsi in un ramo temporaneo e unirlo successivamente con il trunk.

Usando uno distribuito come git o mercurial, penso che sarebbe possibile. Utilizzando un repository "testing" e un repository "stable". Spingi il rappresentante del test, testalo ogni notte e se tutto funziona bene, passi dal test allo stabile. Altrimenti, si esegue il rollback del rappresentante del test. Non sono sicuro di come sarebbe la cronologia delle versioni quando passi dai test a stable, ma penso che sia possibile escludere le cose con rollback non funzionanti. Un po 'di esperimento prima sarebbe il più sicuro.

Un'alternativa sarebbe anche quella di testare il tronco locale di ogni persona ogni notte. Quindi, le persone che hanno superato i test sono autorizzate a inviarlo al server centrale al mattino.


1

IMHO questo non ha nulla a che fare con il VCS che stai usando. L'uso di un ramo "under test" può essere una soluzione, che può essere realizzata anche con VCS centralizzato o distribuito. Ma onestamente, penso che la cosa migliore nella tua situazione sia cercare di ottimizzare la suite di test medi (sembra che contenga i test più importanti) in modo che funzioni molto più velocemente, quindi puoi usarla per il pre-commit-to-trunk test, proprio come lo fai ora con la tua "piccola suite".


Qui sto principalmente chiedendo della metodologia - vale a dire, c'è un modo comune per affrontare una situazione del genere. Supponiamo, almeno per il bene di questa discussione, che i test non possano essere ottimizzati oltre ciò che sono già.
Quercia

@Oak: qualcuno qui (tu?) Ha votato la mia risposta, ma a volte le cose che non vuoi sentire sono le uniche cose che ti aiuteranno. Come vedi nella discussione sotto la tua domanda, altri hanno suggerito lo stesso, quindi il mio suggerimento non sembra affatto essere così male.
Doc Brown,

+1, questa è la risposta giusta. La vera domanda del PO è "Aiuto, sto affogando nella merda, quale metodologia posso usare per aiutare me stesso?" e la risposta è che davvero la metodologia non è ciò di cui dovresti preoccuparti.
MrFox,

1

Test dei supporti non riusciti: è vero che il più delle volte gli stessi test falliscono?

Se si verifica un errore, ci sono sempre gli stessi test correlati che falliscono?

Se vero: può essere possibile selezionare selettivamente alcuni test medi che spesso falliscono (un test per ogni classe di errore) ed eseguirli all'interno di un piccolo set.

La maggior parte dei test di integrazione sono test che utilizzano un database reale? In tal caso è possibile sostituirli con un unittest che ha un database deriso?


1

Devi eseguire i test più velocemente, non c'è altro modo per quadrare questo cerchio.

Considera il problema: vuoi essere sicuro che al momento del check out, hai un codice funzionante. Certo, puoi ritardare gli commit e fare ramificazioni fino a prima del rilascio, ma ciò ritarderà solo l'insorgenza del problema fino all'integrazione. Come in, dovrai eseguire la suite di una settimana dopo ogni unione? La metodologia non è la soluzione, la soluzione è puramente tecnica.

Ecco cosa suggerisco:

1) Rendere i test il più possibile atmomici e massimizzare il riutilizzo dell'ambiente.

2) Ottieni una farm di suite di test per eseguirli. Se invece di 8 grandi moduli finisci con 50, puoi creare un gruppo di istanze spot di Amazon EC2 ed eseguire l'intera suite in parallelo. Sono sicuro che questo costerà un po 'di denaro, ma farà risparmiare enormi quantità di tempo agli sviluppatori.


0

La cosa fondamentale che stai dando per scontato nella tua domanda è che tutti i commit devono superare i test. Mentre questa è una bella regola da seguire e sembra avere un senso, a volte non è pratica. Il tuo caso è un esempio (anche se MadKeithV fa un punto), e posso immaginare di mantenere un ramo VCS così incontaminato potrebbe essere difficile se non ci fosse sufficiente cooperazione tra i devlopers.

In realtà quello che vuoi è sapere in qualche modo quali commit passano o falliscono. Un "ramo pre-commit" come hai suggerito avrebbe funzionato, ma ciò potrebbe richiedere uno sforzo extra da parte degli sviluppatori quando effettuano i commit, che potrebbe essere difficile da vendere.

Un approccio simile che potrebbe essere più semplice è quello di lasciare il bagagliaio perché le persone possano rompersi a loro piacimento e avere un ramo per le commit che non sono rotte. Uno script automatico potrebbe passare attraverso i commit mentre vengono fatti sul trunk, eseguire i test su di essi e aggiungerli al ramo se passano.

Oppure potresti essere assurdamente semplicistico e avere uno script che elenca i commit di passaggio in un file di testo (che può essere o meno controllato dalla versione stessa).

Oppure disporre di un sistema batch che accetti le richieste di rami / revisioni da testare (da qualsiasi parte dell'albero) e le testa e le trasferisce al tronco (o un altro ramo) se passano.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.