Che cosa puoi fare riguardo alla qualità dell'integrazione esistente e ai test unitari pur essendo il nuovo ragazzo di una squadra?

21

Un tema ricorrente che ho incontrato nella mia carriera è essere il nuovo sviluppatore per arrivare in un team, e avere rapidamente una sfiducia intrinseca nei confronti delle unità di test esistenti e di integrazione.

Durante l'intervista ti viene detto dal management che "sostengono strongmente i test unitari" e che lo incoraggiano apertamente. Lo fanno, ma tutto ciò che riguarda gli stessi test è semplicemente sbagliato. Come il fatto che rivendicano una copertura del 100% quando c'è una copertura del test di integrazione del 100% ma meno del 10% di copertura del test dell'unità ripetibile. Alcuni altri problemi che ho trovato:

  1. Nessuna chiara indicazione tra cosa è un test unitario e cosa è un test di integrazione. I test di unità e integrazione sono mescolati insieme nella stessa classe.

  2. Test di integrazione con dipendenze esplicite non dichiarate su dati dinamici molto specifici su un database di un ambiente specifico.

  3. Test di integrazione non transazionale, fondamentalmente test che possono o non si preoccupano di ripulire se stessi, a volte richiedono "scrubbing" manuale del database per rendere ripetibile il test.

  4. Non c'è nessun tipo di derisione e il codice dell'applicazione richiede un'importante revisione solo per il mocking. In altre parole, progettazione senza test in mente.

  5. Nessuna convenzione di denominazione chiara per esaminare rapidamente il nome di un test e determinare approssimativamente quali test vengono eseguiti.

Questo non vuol dire che TUTTI i test sono inutili o cattivi, una buona parte di questi sono abbastanza buoni e degni di essere mantenuti, ma a volte è come cercare l'oro. Eviterei volutamente di eseguire i test solo perché avevo paura di rovinare il database per i miei casi di test black-box.

Questo mi ha essenzialmente dato una sfiducia intrinseca di test di unità e integrazione che non ho personalmente scritto o recensito in alcun modo. Ad un certo livello, se non hai fiducia nella qualità della tua suite di test, allora non apporta alcun valore alla squadra o al progetto.

Che cosa fai quando ti trovi in questa situazione? Quale pensi che il miglior piano di attacco sarebbe quello di affrontare qualcosa di simile?

Tutti i test dovrebbero essere sottoposti a refactoring in uno sforzo monumentale che copre tutte le versioni? Dovresti semplicemente abbandonare l'idea che questo progetto legacy possa avere un giorno di copertura del test unitario?

    
posta maple_shaft 08.09.2011 - 15:01
fonte

7 risposte

6

Prima di tutto, come altri autori hanno già scritto, dovresti essere felice che il test di unità / integrazione sia compreso (non in modo tecnico, intendo il motivo per cui dovrebbe essere fatto) e spinto dalla direzione.

Prima di iniziare a fare tutto, devi esporre i problemi alla gestione, perché qualcosa dovrebbe essere fatto e molto diplomaticamente in modo che non pensino che pensi di essere il miglior programmatore del mondo (anche se lo sei!): -). Forse ti diranno che l'applicazione sarà sostituita da qualcosa di completamente nuovo, e se è così, perché preoccuparsi. E forse capiranno che sarebbe bello e accelerare la fase di test prima di ogni uscita. E sii diplomatico con i tuoi compagni di squadra , ci possono essere milioni di motivi per cui è così com'è e non c'è alcun motivo per cercare un colpevole.

Un'idea migliore sarebbe quella di provare a parlare con loro in modo che possano partecipare allo sforzo, e avrai meno possibilità di apparire come uno stupido, sarebbe più "noi" che "io".

Ora, metti le priorità su ciò che vuoi fare. Dai la priorità ai compiti, sapendo sempre che la tua prima priorità sarà sempre il tuo attuale incarico di progetto ... Per quanto riguarda il tuo problema di test, ecco cosa farei, in tre fasi:

  1. Come fare la differenza tra i test di unità e di integrazione? Le seguenti soluzioni possono essere applicate e non sono esclusive:

    • Riforma il nome dei metodi di test case (non le classi poiché il comportamento corretto è di avere il caso di test condividere lo stesso nome della classe testata)
    • Crea due annotazioni, una denominata "UnitTest", l'altra "IntegrationTest". Queste annotazioni possono essere utilizzate su classi e metodi. Se un'intera classe è composta da unità o test di integrazione, puoi contrassegnare la classe con l'annotazione corretta. In caso contrario, è possibile contrassegnare ciascun metodo con l'annotazione corretta. Inoltre, queste annotazioni potrebbero essere utili per iniettare dinamicamente le fixture prima di lanciare i test (fase 3)
  2. Per ciascun test di integrazione, elencare quale è il "set di dati" che ci si aspetta di essere nel database all'inizio di ogni test e cosa dovrebbe essere rimosso alla fine di esso (es: tabella X, necessita un record con "id" impostato su "1" e "name" su "foo", ecc.). Nota che ciò che rimuovi potrebbe essere più grande / più piccolo di quello che hai all'inizio poiché il codice stesso può rispettivamente aggiungere / rimuovere oggetti dal livello di persistenza. Molto probabilmente noterai rapidamente che molti di questi casi di test richiedono lo stesso set di dati o parte dello stesso set di dati.

  3. Le prime due fasi possono essere eseguite in tempi relativamente brevi ... rispetto al resto. Ora che si dispone del set di dati, si utilizzano le fixture dei dataset create per ogni caso di test che ne ha bisogno. Ma costerà un po 'di tempo ... Quindi potresti farne uno, vedere quanto tempo ti costa e stimare quanto più tempo hai bisogno di fare tutto. Inoltre, puoi usare quel test per dimostrare ai tuoi colleghi che cosa hai fatto e perché la vita è molto più semplice quando non hai bisogno di avere un database in uno specifico stato per fare dei test.

È possibile notare che le fasi 1, 2 e 3 possono essere eseguite in una singola classe di test, se si desidera mostrare rapidamente ai colleghi / alla direzione come può essere fatto. Ciò sarebbe anche utile, come ha scritto Péter Török, per mostrare immediatamente la "buona strada" ai tuoi compagni di squadra in modo che smettano di produrre codice cattivo. Tuttavia penso che il resto della fase 2, che identifica l'intero set di dati di test, sia fatto meglio in un grande passo.

Per quanto riguarda l'API / la tecnologia alla base di tutto ciò, sembra che tu conosca l'argomento.

Spero di aver contribuito un po '.

Nota: per la mia proposta, suppongo che il codice sia in Java / C # dove so che le annotazioni e AOP sono possibili. Sono sicuro che questo è possibile anche in altre lingue, ma non scriverò su qualcosa che non conosco.

    
risposta data 08.09.2011 - 18:07
fonte
14

Non sarai in grado di risolvere tutti i test insieme. Penso che dovresti concentrarti sulla parola miglioramento contro revisione . Né la direzione né gli sviluppatori saranno d'accordo su una revisione, ma se dimostrerai che c'è un modo per migliorare le cose senza influenzare negativamente il progetto, sarà più probabile che ascolteranno.

Innanzitutto, non è possibile "correggere" o rifattorizzare il codice esistente a meno che non si disponga della copertura del test di qualità, quindi mi concentrerei innanzitutto sulla risoluzione dell'infrastruttura di test.

Fai una lista di cose che necessitano di miglioramenti e cerca di dare loro la priorità. Penso che la capacità di eseguire test indipendentemente e singolarmente (in modo che non si influenzino a vicenda) e la separazione dei test di unità e integrazione siano alcune delle prime cose su cui lavorare. Devi rendere facile per te e gli altri fare la cosa giusta.

Per quanto riguarda il codice dell'applicazione ... non sarà possibile eseguire la revisione completa dell'architettura dell'applicazione solo per poter essere testato su un'unità migliore. Invece, quando inserisci un nuovo codice, prova ad applicare i principi che rendono più facile il test unitario (come l'iniezione di dipendenza). Potresti pensare che questo non sia abbastanza grande di un cambiamento, ma è incredibile quanto velocemente gli sviluppatori si accorgano se vedono il vantaggio. C'è solo bisogno di essere qualcuno che inizia a fare un cambiamento per il meglio.

Parla con la tua squadra e portali al buy-in. Una delle cose più importanti che puoi fare è seguire la " Regola dei boy scout " e apportare piccoli miglioramenti per lasciare una classe o un test in una forma migliore dopo averla trovata . Se tutta la squadra applica questa regola, le cose migliorano molto più velocemente.

Dopo un po ', avrai un sacco di codice che segue i buoni principi e le aree dell'applicazione che sono in cattive condizioni. A questo punto, hai una base di ciò che è buono e il team può decidere se è vantaggioso fare un refactoring più grande per il materiale legacy più vecchio o può semplicemente continuare a vivere così com'è.

    
risposta data 08.09.2011 - 15:31
fonte
10

Devo ammettere che lo prenderei come un regalo raro per arrivare a un progetto in cui hanno già un numero significativo di test di unità / integrazione - non ho mai avuto quella fortuna nella mia vita fino ad ora. Anche se non tutti stanno lavorando come dovrebbero, ci sono già molti sforzi da fare e anche se il team e il management non seguono sempre le migliori pratiche, sono già impegnati nella causa, quindi tu non è necessario perdere tempo a discutere sul motivo per cui vale la pena scrivere i test unitari.

Tuttavia, i test così come li descrivi possono effettivamente migliorare. Ma devi stare attento con il tuo tono quando discuti dei problemi con i tuoi compagni di squadra . Se inizi a dire "tutto ciò che riguarda i test stessi è semplicemente sbagliato" , potresti finire molto rapidamente per alienare il resto della squadra. Invece, dovresti concentrarti su come migliorare lo stato attuale delle cose, che - devo ripetere - è ancora significativamente migliore della media secondo la mia esperienza fino ad ora.

IMO il tuo primo obiettivo dovrebbe essere quello di impedire al team di produrre altri test non validi . Quindi inizia dimostrando il beneficio di ogni specifico miglioramento per i tuoi compagni di squadra. Se vedono l'utilità di una determinata tecnica - che tagli le dipendenze esterne, ripristina lo stato originale dopo ogni test o separa i test di unità e integrazione - inizieranno ad applicarle. Questo di per sé lentamente ma sicuramente migliorerà la qualità complessiva della base di test nel lungo periodo (se hai 1000 casi di test non validi ora, e il team produrrà 1000 buoni test entro l'anno prossimo, avrai abbassato il rapporto tra i test non validi dal 100% al 50%). Una volta assicurato, puoi decidere di eseguire di nuovo i test esistenti caso per caso. Ancora una volta, piccoli miglioramenti si sommano a grandi cambiamenti nel tempo.

Come nota a margine, dal tono del tuo post sento che potresti trovarti in un posto in cui ero anche io: non fidarmi del lavoro svolto da altri, incapace di delegare compiti a chiunque temesse che il loro lavoro non fosse fino ai tuoi standard di qualità. Nella mia esperienza, questo non è un buon posto dove stare, perché a lungo andare potrebbe portare facilmente a conflitti personali e burnout. Non puoi fare tutto da solo, devi lavorare insieme al resto della squadra. Puoi avere successo solo insieme.

    
risposta data 08.09.2011 - 16:10
fonte
6

Lavorare per verificare l'indipendenza. Se il test X modifica il database di test in modo tale che il test Y fallisca, allora cambia il test Y. In questo piccolo scenario la cosa su cui concentrarsi non è che X ha incasinato il database, ma piuttosto che Y ha dipendenze inappropriate. Rimuovi quelle dipendenze (estraendo il database, ristrutturando il test o inizializzando il database in uno stato in cui passerà Y) e ora hai un altro test di lavoro indipendente. Questo è progresso (probabilmente, "aggiustare" X per non rovinare il database non sarebbe).

Sii paziente e rispettoso, il meglio che puoi, delle persone con cui lavori, nonostante il disastro che hanno creato. Stanno cercando di fare la cosa giusta, con ogni probabilità; tienilo a mente e aiutali a farlo.

    
risposta data 08.09.2011 - 16:19
fonte
2

Il bello dell'essere nuovi nel team è che hai un approccio "fresco" alle cose. La parte cattiva potrebbe essere che altri potrebbero avere difficoltà a crederti.

Non fare una lista di cose da fare. Scegli una cosa che sembra urgente e che è più probabile che gli altri rispondano e suggerisci una soluzione. Se funziona, ottimo, allora suggerisci un'altra soluzione ad un altro problema, in base al tuo primo successo.

Ma prendilo piano, uno per uno, e spera che le tue idee "prendano lentamente piede" nel nuovo gruppo.

    
risposta data 08.09.2011 - 19:52
fonte
2

imposta l'esempio che vuoi vedere, ma apprezza il punto di vista di un altro sviluppatore in un test: uno sviluppatore può testare per i successi, mentre un altro può testare errori, uno sviluppatore ha scritto la classe mentre un altro potrebbe averlo usato la prima volta durante la scrittura il test.

i test esistenti (ehm, la maggior parte) hanno ancora uno scopo, anche se potrebbe non essere immediatamente evidente. Non consiglio di revisionare e refactoring di tutto in una volta (è noioso e soggetto a errori). i test non validi devono essere aggiornati, riscritti o potrebbero semplicemente diventare obsoleti con l'evolversi del software.

se il tuo approccio al testing è superiore per alcuni aspetti, le persone impareranno da quel modello o ti chiederanno la tua assistenza. ci sarà un equilibrio di risorse, ma puoi estenderlo come necessario per supportare i tuoi test.

In definitiva, si desidera aumentare la qualità dei programmi tramite test e migliorare la copertura. puoi farlo ponendo maggiore enfasi sul test e dando il buon esempio, ma apprezza le prospettive altrui.

quando si enfatizza l'importanza, è possibile rendere diverso l'ambiente operativo dei test: un ovvio esempio è eseguire test in parallelo; se non è rientrante, hai individuato un bug nel tuo programma o test (vinci / vinci). un ambiente di test più rigoroso costringerà i cattivi test a essere riparati e / o riscritti (si spera nel modo giusto la seconda volta). introducete lentamente tali cambiamenti (non rompete la metà dei test tutti in una volta - questo è un problema reale), costringendoli a imparare ciò che rende un buon test e, infine, un buon programma. quindi quando tu e altri partecipate e modificate / riparate / estendete i test, applicate ciò che avete appreso - è incrementale e avete una migliore comprensione del contesto / programma in quel momento.

    
risposta data 09.09.2011 - 00:50
fonte
2

Correggi nel tempo

Sono stato nella stessa situazione. Ho passato solo un'ora ogni mattina a esaminare i test e a correggerli fino a quando non sono stati tutti riparati. Era un codebase di medie dimensioni e penso di aver finito in 1,5 mesi. Ho anche avuto molta più fiducia nei nostri test.

Personalmente non mi interessa se un test è un test unitario o un test di integrazione purché sia un buon test. Per buona prova intendo che:

  • ripulisce se stesso
  • è ripetibile
  • riduce al minimo le interazioni ambientali
  • è coerente

Lungo il cammino ho evangelizzato la costruzione di test migliori (vale a dire ho infastidito molte persone).

    
risposta data 08.09.2011 - 22:35
fonte