Come gestire un numero enorme di test falliti? [chiuso]


22

Sto lavorando allo sviluppo di un vecchio progetto scritto in Java. Abbiamo oltre 10 milioni di LOC e, peggio ancora, più di 4000 test funzionali.

I test, programmati da Hudson, stanno fallendo come un matto ad ogni più grande modifica del codice. Verifica del fallimento del test - se si tratta di un problema nel prodotto o nel test, ci vogliono mesi. Non possiamo rimuovere i vecchi test perché non sappiamo cosa stanno testando!

Ciò che possiamo fare? Come procedere con tale quantità di test legacy?


6
Le domande reali hanno risposte. Invece di spiegare perché la tua situazione è terribile o perché il tuo capo / collega ti rende infelice, spiega cosa vuoi fare per renderlo migliore. Per maggiori informazioni, clicca qui ...
moscerino del

13
Perché hai permesso che i test iniziassero a fallire in primo luogo? BTW 4000 non è che molti test per 10 MLOC
BЈовић

6
Fermati, rilascia e rotola.
Navin,

13
Scopri cosa stanno testando i test. Quindi rivisita e chiediti innanzitutto come mai i test sulla terra impiegano mesi per trovare un problema, e scopri anche come le tue esigenze sono cambiate così tanto. I test hanno lo scopo di incapsulare i requisiti in un'applicazione. Se i test non hanno esito positivo, il codice non viene eseguito in base ai requisiti: o li hai scritti in modo errato o nessuno dei codici rispetta i tuoi requisiti.
Dan Pantry,

6
Abbiamo visto tutti un compilatore dare il via a milioni di errori a causa di un singolo '}' mancante. Se questi sono test funzionali con una pletora di dipendenze, forse lo stesso tipo di problema è al lavoro?
Dan Pichelman,

Risposte:


37

Abbandonali.

So che è difficile lasciar andare qualcosa che è stato chiaramente un grande sforzo per produrre, ma i test non funzionano per te, stanno lavorando contro di te. Una suite di test dovrebbe darti la sicurezza che il sistema fa quello che dovrebbe fare. Se non lo fa, è una responsabilità anziché un bene. Non importa se il sistema o i test sono in errore - fintanto che l'esecuzione della suite di test segnala enormi quantità di errori, non può raggiungere il suo scopo.

Ciò di cui hai bisogno ora è una nuova suite di test che viene eseguita senza errori. Ciò significa che inizialmente avrà poca copertura, in realtà quasi nessuna copertura. Ogni volta che aggiusti o prendi il tempo necessario per comprendere a fondo qualcosa sul tuo sistema, riordini quella conoscenza in un test. Nel tempo, questo produrrà una nuova rete di sicurezza su cui puoi costruire in futuro. Cercare di riparare una vecchia rete di sicurezza mal compresa è una perdita di tempo che non vale quasi mai la pena.

Vorrei persino difendere il trasferimento dei test dalla vecchia suite alla nuova suite. Certo, alcuni di loro potrebbero avere successo ora, ma è perché stanno testando esattamente ciò che dovrebbero testare, o solo perché alcuni colpi casuali colpiscono sempre il bersaglio? Ovviamente devi essere pragmatico su ciò che può e non può essere fatto con lo sforzo che hai a disposizione per spendere, ma non puoi scendere a compromessi sul principio che una suite di test deve essere eseguita in modo pulito per fare il suo lavoro .


9
Non riesco a vedere la logica nel tuo punto: "Una suite di test dovrebbe darti la sicurezza che il sistema fa quello che dovrebbe fare. [...] Ciò di cui hai bisogno ora è una nuova suite di test che viene eseguita senza errori." Se hai un codice difettoso che fa fallire i test non significa che devi riscrivere i test in modo che il codice difettoso passi.
DBedrenko,

13
La situazione di Hector è che non sa se il codice o i test sono sbagliati . In tal caso, potrebbe lavorare con la base di codice e modificare a volte i test, a volte il codice aziendale. Così com'è, anche questo tipo di lavoro non pagherebbe, dal momento che non sai se stai risolvendo problemi o perpetuandoli.
Kilian Foth,

5
"Una suite di test dovrebbe darti la sicurezza che il sistema fa ciò che [dovrebbe]." No, dovrebbe dirmi se il sistema fa quello che dovrebbe; la falsa fiducia è peggio di niente. "Ciò di cui hai bisogno è una suite di test che viene eseguita senza errori" No, ciò di cui ha bisogno è una suite di test che gli fornisca informazioni utili sulla validità del codice. Quello che ha ora sono molte spie criptiche, che sono meglio di una luce verde di una nuova suite di test brillante che non verifica nulla. Dovrebbe disabilitare temporaneamente i vecchi test , ma non abbandonare quelli che non ha ritenuto falsi.
Beta,

4
Questa risposta è un consiglio incredibilmente negativo! Se piccole modifiche al codice portano a una grande quantità di test falliti, probabilmente hai problemi di qualità del codice. Il test ti avviserà almeno che hai rotto qualcosa. È necessario migliorare il codice (eseguendo il refactoring con attenzione aiutato dai test). Se rimuovi i test non hai modo di sapere se rompi qualcosa.
JacquesB,

4
Questo è un consiglio terribile. Se l'OP e il suo team non sono già in grado di comprendere la base di codice e i relativi test, è improbabile che lanciare i test e ricominciare da capo risolva il problema principale dell'OP: comprendere la base di codice. Penso che possiamo supporre che i test abbiano funzionato quando sono stati scritti, quindi il suo team ha bisogno di rintracciare ciò che ogni test sta testando e leggere la fonte per determinare se è la base di codice o il test che è sbagliato oggi. Molto più semplice che ricominciare con test mal guidati e non informati / ingenui.
SnakeDoc,

29

Vai e correggi i test.

Il tuo più grande errore è che hai permesso ai test di fallire, e ovviamente l'hai ignorato per un po '. Quello che hai non sono "test legacy" - stai lavorando su un codice legacy. E considero ogni codice scritto senza test come eredità.


Verifica del fallimento del test - se si tratta di un problema nel prodotto o nel test, ci vogliono mesi. Non possiamo rimuovere i vecchi test perché non sapevamo cosa stavano testando!

Sembra che ci sia un problema ancora più grande nella tua organizzazione, dal momento che non stai lavorando con requisiti chiari. Non riesco a capire che tu (o qualcun altro) non sia possibile confermare il comportamento corretto.


4
Questo è ciò che dovrebbe idealmente essere fatto, ma sembra che i test qui siano così male che i programmatori non sappiano nemmeno cosa stanno testando. Penso che in questo caso potrebbe essere meglio sbarazzarsi dei test WTF e iniziare subito a scriverne di nuovi e significativi! In un recente progetto ho avuto un problema simile con un collega i cui test hanno sempre fallito senza buone ragioni (non è fallito perché ciò che doveva essere testato era sbagliato, ma perché il codice del test era così fragile e nemmeno deterministico!) . Ho passato giorni a riscrivere ciò che potevo e ho distrutto il resto!
Shautieh,

@Shautieh I test WTF non vanno senza il codice WTF, quindi riparare i test di solito significa refactoring del codice. E i test casualmente falliti sono il segno di incompetenza. E il supervisore del tuo collega è la colpa per non aver fatto il proprio lavoro.
BЈовић,

2
A volte la vita è dura: il ragazzo responsabile dei test (e del codice) del WTF ha guadagnato lo stipendio più alto nel team (20% in più di me) e quando ha lasciato il centro del progetto (perché ha trovato un lavoro più remunerativo ) Ho dovuto affrontare alcuni dei suoi sviluppatori: / Ma hai assolutamente ragione a dire che anche il nostro supervisore era da biasimare ^^
Shautieh,

@Shautieh: un mio collega una volta ha detto che un bug nel codice è due bug: un bug nel codice e un punto cieco nei test. Immagino che in realtà siano tre se si considera lo sviluppatore che tollera i test falliti e quattro se si contano i manager che promuovono un tale incompetente.
Beta,

@Beta Sembra abbastanza simile alla definizione talvolta usata in TDD: "Un bug è un test che non hai ancora scritto."
Ripristina Monica il

22

I test sono preziosi. Per lo meno, registrano che qualcuno ha pensato che avrebbero dovuto trascorrere del tempo a scriverli, quindi presumibilmente avevano un certo valore per qualcuno una volta. Con un po 'di fortuna, conterranno un registro completo di tutte le funzionalità e i bug su cui il team ha mai lavorato, anche se potrebbero anche essere stati un modo per raggiungere un numero arbitrario di copertura del test senza essere attentamente esaminati. Fino a quando non li guardi, non saprai quale sia il caso qui.

Se la maggior parte dei test passa per la maggior parte del tempo, morde semplicemente il proiettile e investi il ​​tempo a capire quali sono stati i pochi test che hanno fallito e risolverli o migliorarli in modo che il lavoro sia più facile la prossima volta. In tal caso, passare alla sezione Determina l'intento per ciascuna sezione di test , per alcuni consigli su cosa fare con un numero limitato di test non riusciti.

D'altra parte, potresti dover affrontare una build Red ora e centinaia o addirittura migliaia di test che non sono passati da un po 'di tempo e Jenkins non è verde da molto tempo. A questo punto, lo stato della build Jenkins è diventato inutile e un indicatore chiave dei problemi con il check-in non funziona più. Devi risolvere questo problema, ma non puoi permetterti di fermare tutti i progressi mentre riordini il disordine nel tuo salotto.

Al fine di mantenere la sanità mentale durante l'esecuzione dell'archeologia richiesta per determinare quale valore può essere recuperato dai test che hanno fallito, raccomanderei i seguenti passaggi:

Disabilitare temporaneamente i test non riusciti.

Ci sono diversi modi in cui potresti farlo, a seconda del tuo ambiente, che non descrivi chiaramente, quindi non posso davvero consigliarne uno in particolare.

Alcuni framework supportano la nozione di guasti previsti. Se il tuo lo fa, allora è fantastico, poiché vedrai un conto alla rovescia di quanti test sono rimasti in questa categoria e verrai anche informato se alcuni di loro iniziano a passare inaspettatamente.

Alcuni framework supportano gruppi di test e consentono di dire a Hudson di eseguire solo alcuni dei test o di saltare un gruppo di test. Ciò significa che occasionalmente è possibile eseguire manualmente il gruppo di test per vedere se qualcuno sta passando.

Alcuni framework consentono di annotare o contrassegnare in altro modo i singoli test da ignorare. In questo caso è più difficile gestirli come gruppo, ma impedisce loro di distrarti.

È possibile spostare i test su un albero di origine che normalmente non è incluso nella build.

In extremis, è possibile eliminare il codice dall'HEAD del sistema di controllo della versione, ma ciò renderà più difficile riconoscere quando la terza fase è stata completata.

L'obiettivo è far sì che Jenkins diventi verde il più presto possibile, così puoi iniziare a muoverti nella giusta direzione il prima possibile.

Mantenere i test pertinenti.

Risolvi per aggiungere nuovi test mentre aggiungi o modifichi il codice e ti impegni a mantenere tutti i test che superano.

I test possono fallire per una serie di ragioni, incluso il fatto che non erano test ben scritti per cominciare. Ma una volta che ottieni Jenkins verde, mantenerlo in questo modo è davvero importante.

Abituati a scrivere buoni test e rendilo un grosso problema se i test iniziano a fallire.

Determinare l'intento per ciascun test.

Passare i test disabilitati uno per uno. Inizia con quelli che influenzano i moduli che cambi più frequentemente. Determinare l'intento del test e il motivo del fallimento.

  • Verifica una funzionalità che è stata rimossa dalla base di codice di proposito? Quindi probabilmente puoi eliminarlo.

  • Sta rilevando un bug che nessuno ha ancora notato? Ripristinare il test e correggere il bug.

  • Sta fallendo perché stava facendo ipotesi ingiustificate (ad esempio supponendo che il testo del pulsante sarebbe sempre in inglese, ma ora hai localizzato la tua applicazione per più lingue)? Quindi scopri come focalizzare il test su una sola cosa e isolalo nel miglior modo possibile da modifiche non correlate.

  • Il test si estende su tutta l'applicazione e rappresenta un test di sistema? Quindi rimuovilo dalla tua suite di test Jenkins principale e aggiungilo alla suite di regressione che viene eseguita meno frequentemente.

  • L'architettura dell'app è cambiata oltre il riconoscimento, quindi il test non fa più nulla di utile? Cancellalo.

  • Il test è stato aggiunto per aumentare artificialmente le statistiche sulla copertura del codice, ma in realtà non fa altro che confermare che il codice viene compilato correttamente e non va in un ciclo infinito? Altrimenti, il test conferma semplicemente che il framework di derisione selezionato restituisce i risultati a cui gli hai appena detto? Cancellalo.

Di conseguenza, alcuni test rimarranno, alcuni saranno modificati, alcuni divisi in più blocchi indipendenti di dimensioni ridotte e altri rimossi. Fintanto che stai ancora facendo progressi con i nuovi requisiti, riservare un po 'di tempo per affrontare il debito tecnico come questo è la cosa responsabile da fare.


1
È una pessima idea disabilitare i test solo perché falliscono! Il resto dei tuoi consigli sono buoni, ma non questo. I test che non capisci non dovrebbero mai essere disabilitati. Il punto di test non è quello di ottenere una barra verde, il punto è di far funzionare il software!
Jacques B

Dipende dall'entità del problema. Ma sono d'accordo, non l'ho ancora chiarito.
Bill Michell,

Aggiunto un paragrafo per distinguere tra "siamo verdi ma ogni cambiamento fa diventare le cose rosse" e "siamo stati rossi così a lungo, abbiamo dimenticato che aspetto ha il verde"
Bill Michell,

Invece di disabilitare o addirittura eliminare il test, alcuni framework forniscono anche l'idea di un errore previsto . Questo potrebbe aiutare ad aumentare il SNR perché verrai avvisato più direttamente dei nuovi guasti (cosa che non succederebbe se ci fosse sempre un numero enorme di guasti) ma sarai comunque informato dei guasti noti e - forse anche più importante - quando un il test precedentemente fallito passa improvvisamente di nuovo. Se i guasti imprevisti vengono letti e i guasti previsti diventano arancioni, rendere verdi i primi test rossi e rendere verdi quelli arancioni la seconda priorità.
5gon12eder

11

4000 test è un problema irrisolvibile. 40 test è più tracciabile. Seleziona in modo casuale un numero gestibile di test da eseguire e analizzare. Classificare i risultati come:

  1. Test inutile
  2. Test utile che funziona pulito
  3. Test utile che fallisce

Se molti dei test rientrano nella prima categoria, potrebbe essere il momento di lanciare la tua attuale suite di test e metterne insieme uno utile per il codice corrente.

Se molti dei test hanno esito negativo in modi che indicano un problema nel codice, è necessario eseguire i test con esito negativo per correggere le cose. È possibile che la correzione di uno o due bug faccia eseguire un gran numero di test.


2
+ (int) (PI / 3) per fornire un modo effettivo e semplice di testare la suite di test - mentre sono d'accordo che, come regola generale, test come quelli descritti da OP sono un segno di un design difettoso - ma senza test cosa c'è che non va, qualsiasi consiglio sulla suite di test stessa (che si tratti di "abbandonarli", "correggere i test", "scrivere nuovi test") è semplicemente inutile. Esattamente come dici tu: se avessi 4k test e per 40 completamente casuali di quei 3/4 sono schifosi e inutili - non esiterei a scaricare l'intera suite. Se 3/4 di questi sarebbero stati effettivamente utili, li lascerei e mi concentrerei sul miglioramento del codice.
vaxquis,

7

Se questa affermazione è vera,

I test ... stanno fallendo come un matto con ogni più grande modifica del codice.

quindi ciò implica che se si esegue il rollback al codice appena prima di una "modifica del codice più grande", molti dei test passeranno di nuovo. Dopo averlo fatto, prendi una piccola parte delle modifiche e vedi quali test hanno appena fallito. Questo ti aiuterà a isolare meglio quali modifiche al codice stanno causando quali test falliscono. Per ogni test, una volta isolato il problema, dovresti essere in grado di determinare se il nuovo codice era difettoso o il test lo era. Se si tratta di un problema con il nuovo codice, assicurati di confrontarlo con l'ultima versione nel caso in cui quel particolare bug sia già stato corretto.

Ripeti fino a quando non hai la base di codice più recente.

Questo può sembrare un compito schiacciante, ma è molto probabile che una volta che segui questa strada e inizi a isolare alcuni dei problemi, inizierà a emergere un modello che potrebbe accelerare notevolmente il processo. Per esempio:

  • Potresti notare che molti test dipendono da qualcos'altro che è difettoso. Riparare quel pezzo può risolvere molti test.
  • Potresti notare che molti test sono imperfetti e devono essere riparati o rimossi.
  • È possibile notare che un determinato sviluppatore ha una frequenza molto più elevata di causare l'interruzione dei test. Lo sviluppatore potrebbe aver bisogno di più formazione o supervisione.

3

Se non sai cosa stanno testando, rimuovili finché non lo sai. I test sono cose fluide, se rimuovi una funzione che non è più necessaria, dovresti aspettarti di dover cambiare il test che testa quella funzione! Quindi, a meno che tu non sappia quali test stanno testando, non hai alcuna speranza di cambiare la base di codice con loro in atto.

È possibile configurare il sistema di test sui computer degli sviluppatori ed eseguirli in modo che gli sviluppatori possano vedere con quali parti interagiscono i test, si spera di fornire questa documentazione mancante e acquisire familiarità con la base di codice che non si sta modificando correttamente, oppure no test più lunghi correttamente.

In breve: se i vecchi test falliscono quando si apportano modifiche, le modifiche al codice non vanno bene. Utilizzare questi test come mezzo di educazione su come funziona il sistema.


1
Questo è il motivo per cui mi piace l' @Ignoreannotazione di JUnit : puoi mantenere i tuoi test, ma non eseguirli. Quindi si tratta semplicemente di riattivarli e risolverli uno alla volta. Ti consente di limitare la tua attenzione a una manciata di test alla volta, invece di essere sopraffatto da migliaia di fallimenti.
TMN,

1
Questo è un cattivo consiglio. Non è necessario rimuovere o disabilitare un test che non si capisce. Solo se si fa a capire il test, e si è sicuri mette alla prova una caratteristica obsoleta, dovrebbe essere disattivato o rimosso.
Jacques B

2

La cosa più importante che vorrei fare è tornare ai fondamenti di ciò che i test dovrebbero fare e di cosa l'azienda deve continuare a muoversi. Il compito del test consiste nell'identificare i problemi prima che diventino costosi da risolvere in seguito. Penso che la parola chiave in quella frase sia "costosa". Questi problemi richiedono una soluzione aziendale. Problemi costosi si presentano sul campo? In tal caso, i test non stanno andando a buon fine.

La tua direzione e tu devi venire a un controllo di realtà. Stai scoprendo che i costi di sviluppo sono alle stelle a causa di una serie di test legacy. In che modo tali costi si confrontano con i costi di consegna di un prodotto difettoso perché hai disabilitato i test? Come si confrontano con l'oneroso compito di capire effettivamente quali comportamenti hanno bisogno gli utenti (quali sono le cose che dovrebbero essere testate)?

Questi sono problemi che richiedono soluzioni aziendali perché toccano il lato aziendale del lavoro. State consegnando un prodotto a un cliente, e questo è un limite a cui l'azienda è molto interessata. Potrebbero essere in grado di identificare soluzioni che voi, come sviluppatori, non potete. Ad esempio, può essere ragionevole per loro fornire due prodotti: un prodotto "legacy" per coloro che hanno bisogno di affidabilità e sono disposti a rinunciare a nuove funzionalità, con un prodotto "visionario" che può avere più difetti, ma è all'avanguardia. Ciò ti darebbe l'opportunità di sviluppare due serie indipendenti di test ... uno precedente con 4000 test e uno con più test che ritieni debbano essere eseguiti (e documentali in modo che questo processo non si ripeta).

Quindi, l'arte inizia: come puoi gestire questa bestia a due teste in modo che i progressi in un ramo aiutino anche l'altro ramo? In che modo i tuoi aggiornamenti al ramo "visonario" possono ritornare al ramo "legacy", nonostante i rigidi requisiti di test. In che modo le continue richieste dei clienti sul ramo "legacy" possono migliorare la comprensione dei requisiti di cui i clienti legacy avrebbero bisogno se alla fine si ricongiungessero i prodotti?


-3

Non possiamo rimuovere i vecchi test perché non sapevamo cosa stavano testando!

Questo è esattamente il motivo per cui dovresti rimuovere i vecchi test! Se non sai cosa stanno facendo, allora il fallimento non ha senso e gestirli è una perdita di tempo. Buttali fuori e ricomincia.


2
questo sembra semplicemente ripetere il punto già esposto e spiegato nella risposta migliore
moscerino del

4
Il fallimento non è "insignificante", significa che non capisci il sistema come pensavi di aver fatto.
Ben Voigt,

Il fallimento qui non ha assolutamente senso, perché l'OP ha chiaramente affermato di non capire il sistema.
Mohair,
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.