Dobbiamo sempre unitamente testare i bug quando li correggiamo?


29

Quando correggo i bug, è incoraggiato dove lavoro per prima cosa scrivere un test che non ha esito positivo con il bug dato e quindi correggere il codice fino al completamento del test. Questo segue le pratiche del TDD e dovrebbe essere una buona pratica, ma ho notato che tende a produrre test criptici che si avvicinano molto all'implementazione.

Ad esempio, abbiamo riscontrato un problema durante l'invio di un lavoro, il raggiungimento di un determinato stato, l'interruzione e il tentativo. Per riprodurre questo bug, è stato scritto un enorme test con la sincronizzazione dei thread, un sacco di scherno e roba ... Ha fatto il lavoro, ma ora che sto riformattando il codice, trovo molto allettante rimuovere semplicemente questo mammut, dal momento che richiederebbe davvero molto lavoro (di nuovo) per adattarsi al nuovo design. E sta solo testando una piccola funzionalità in un singolo caso specifico.

Da qui la mia domanda: come testare i bug che sono difficili da riprodurre? Come evitare di creare elementi che testino l'implementazione e danneggino il refactoring e la leggibilità?


Questo caso di errore è rilevante per il nuovo design? Per me parte di un nuovo design sarebbe aumentare l'affidabilità del design, quindi potresti essere in grado di usarlo per giustificare la rimozione di questo caso di test se questo tipo di bug avesse a che fare con un errore nel design originale.
Thymine,

il refactor riguarda qualcos'altro ed è ancora possibile nel nuovo design modificare leggermente il codice e reintrodurre il bug, che è ciò che il test sta guardando. Immagino che un'alternativa al test sarebbe un commento nel codice che dice "non fottere", ma suona come la cosa sbagliata da fare: p
Zonko,

1
se è troppo complesso per un unittest, rendilo parte del test di integrazione
maniaco del cricchetto,

Sembra che questo abbia bisogno di un test di integrazione e non di un test unitario. Basato sul fatto che stai deridendo così tanto. Una regola generale che ho visto è che non testate il codice che comunica con componenti esterni alla vostra base di codice (parlare con un database, leggere dal file system, ecc.) Che suona anche come quello che sta facendo.
Lucas,

Risposte:


27

Sì, in generale dovresti . Come per tutte le linee guida, dovrai usare il tuo miglior giudizio quando si scontrano con altre linee guida. Per questo scenario, la gravità del bug deve essere ponderata rispetto al lavoro necessario per implementare il test e alla qualità di quel test nel mirare al problema aziendale e catturare la regressione dello stato del bug.

Tenderei a preferire non scrivere test, poiché le interruzioni per il malfunzionamento dei bug tendono ad avere più costi del semplice sviluppo e mantenimento di un test unitario.


Aggiungerei maggiore enfasi a questo e affermerei che in un mondo ideale sarebbe considerato un bug solo se esistesse un test unitario fallito, ma +1 per il corsivo e notando che le esigenze aziendali dovrebbero prevalere.
Joshua Drake,

2
beh, in effetti, alla fine si tratta di un equilibrio tra il tempo necessario per mantenere il test rispetto al tempo impiegato da un noob per rilevare e correggere il bug se si ripetesse.
Zonko,

Preferirei anche generalizzare il test in modo che non si tratti solo di provare a interrompere e ritentare il lavoro quando raggiunge uno stato specifico, ma piuttosto test di interrompere e riprovare in ogni stato in cui un lavoro potrebbe trovarsi.
Vecchio Pro

+1 per "poiché le interruzioni per il downgrade dei bug tendono ad avere un overhead maggiore rispetto al semplice sviluppo e mantenimento di un test unitario".
Peter K.,

16

Penso che la migliore pratica - quella che mi imbarazza nell'ammettere che non seguo spesso - sia quella di creare un test di sistema o di integrazione che dimostri il problema osservato in produzione, quindi fare delle ricerche per trovare le unità responsabili del problema, e quindi scrivere test unitari per quelle unità che dimostrano il problema a livello di unità . Dopo aver effettuato i test delle unità, sistemare le unità ed eseguire tutti i test. A questo punto, può essere prudente scartare il test originale, perché potrebbe essere fragile e / o lento, ma mantenere i test unitari nella suite automatizzata per motivi di regressione e copertura.


7

La pratica di scrivere un test per identificare il difetto è una buona idea, poiché ti consente di identificare esattamente quali passaggi sono necessari per riprodurre il difetto e verificare che sia stato corretto. Inoltre, questi test possono essere eseguiti come parte dei test del fumo o dei test di regressione per garantire che le modifiche successive non abbiano reintrodotto un vecchio difetto nel sistema.

La prima cosa da considerare è il livello del test necessario. Forse il test per verificare la correzione sarebbe più appropriato a livello di sistema, o forse anche un test di accettazione che viene eseguito manualmente. Penso che sia più importante avere un test documentato e gestito, indipendentemente da come sia implementato in modo specifico.

Per quanto riguarda il modo in cui il refactoring influenza i test, dipende dalle caratteristiche specifiche. In alcuni casi, il refactoring (o qualsiasi tipo di lavoro, come le nuove funzionalità) potrebbe rendere i test non più necessari. Il problema, come si era originariamente verificato, potrebbe non essere più possibile. In tal caso, potrebbe essere saggio rimuovere il test dai possibili test per rendere il processo di test (automatizzato o manuale) più snello. In altri casi, esistono diversi metodi per eseguire il test e verificare che la funzionalità a un livello diverso sia più appropriato. Se la funzionalità è minore, forse il test non è più necessario.

Puoi anche considerare non solo di fare affidamento sui test, ma anche di accedere. Ad esempio, acquisire informazioni in fase di esecuzione (con livelli variabili di verbosità a seconda dell'ambiente - più dettagli durante i test, meno dettagli durante l'implementazione), profilare l'applicazione, acquisire dump dello stato corrente del sistema. Se riesci a trovare trigger comuni al problema, puoi utilizzarlo per guidare i test a tutti i livelli.


5

Si, dovresti.

Scrivi unit test per code base esistenti. Quando correggi un bug, devi assicurarti che il test unitario fallisca - questo ti darà la certezza che stai davvero lavorando su un bug. È quindi necessario ricodificare e completare il test risolvendo il bug.

Questa non è una pratica TDD però. Nei test TDD guidare il tuo design, ma nel tuo caso il design è già stato deciso.

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.