I test dell'unità che non verranno risolti non verranno rimossi? [duplicare]

13

Il mio collega ama vedere passare tutti i nostri test unitari (come chiunque altro) e sostiene che alcuni dei test non riusciti di un sistema che ha scritto sono "rumore" non necessari poiché coinvolgono tutti la validità dei dati e un separato il sistema nel nostro stack dovrebbe essere responsabile della convalida.

Personalmente, ritengo che mantenere i test ti permetta di capire / riconoscere almeno alcuni dei punti critici, anche se hai scelto consapevolmente di non risolverli.

Ha ragione nel volere che vengano rimossi dal momento che sono "rumorosi" rispetto alle altre funzionalità testate e probabilmente non verranno mai riparati?

Solo per contesto. Ecco alcuni esempi concreti. Tutti coinvolgono percorsi di codice che vengono utilizzati, ma il passaggio di dati non convalidati nelle routine causa comportamenti imprevisti.:

  • passare in NaN produce un falso positivo.
  • il passaggio di un valore che supera le cifre significative di un doppio si traduce in false quando dovrebbe essere stato restituito true. Arrotondamento non dovrebbe verificarsi.
    • "139.9999999999999" - > Double.TryParse () - > 139.9999999999999
    • "139.99999999999999" - > Double.TryParse () - > 140
posta Brandon Boone 02.05.2014 - 22:17
fonte

9 risposte

23

Vorrei iniziare con alcune affermazioni:

  • I test vengono utilizzati per mostrare dove fallisce il codice.
  • I test dovrebbero coprire tutti gli scenari per ciascuna unità che vuoi testare.
  • I risultati del test dovrebbero fornire una visione chiara di cosa è andato storto.

Ora vai al tuo scenario: riconosci che questi test sono scritti in una posizione a cui non appartengono. Presumo dalla tua storia che tu abbia un progetto separato che testa tutta la validazione, quindi perché non sposti questi test in quel progetto?

Gli svantaggi derivanti dal tenere questi test a cui non appartengono:

  • I test sono frammentati durante i progetti anche se hanno un posto designato per tenerli insieme.
  • La panoramica su quali test fallimentari sono rilevanti e quelli che vengono consapevolmente ignorati diventa più difficile e potresti perdere alcuni nuovi test di rottura.

Detto questo: rimuovere i test solo perché vuoi vederli tutti passare è non la risposta. La soluzione preferita è ovviamente quella di risolverli ma, quando ciò non è possibile, potresti volerli classificare in un progetto separato.

Va anche notato che i test duplicati non sono neanche buoni. Se hai due test in due diversi progetti che testano la stessa identica cosa, devi fare manutenzione per due mentre ottieni solo benefici da uno. Se collaudi la convalida nel progetto ValidationTest e fai lo stesso nel tuo altro progetto, allora dovresti rimuovere quelli nel tuo altro progetto e tenere le cose contenute dove dovrebbero essere.

Infine, potresti anche voler utilizzare le possibilità del framework di test. Ad esempio, MSTest ti permetterà di aggiungere un attributo [Ignore] ai test che dovrebbero essere ignorati. Ciò si tradurrà in una bella barra verde con una categoria aggiuntiva di test ignorati, mantenendoli così prevalenti.

    
risposta data 02.05.2014 - 22:39
fonte
7

Dipende ...

Se i test non validi appartengono a funzionalità che non vengono scartate, non dovrebbero essere rimosse.

Come probabilmente saprai, l'intero punto dei test unitari sarà quello di essere in grado di testare rapidamente e rapidamente tutti i piccoli bit e pezzi del tuo codice su un livello micro per determinare che ogni piccolo componente stia facendo quello che dovrebbe. Se un componente è ancora in uso, dovrebbe comunque avere un test ...

La prossima domanda è perché stanno fallendo? I test dovrebbero essere spostati in una posizione più appropriata per i test? c'è stato un cambiamento nel design del sistema che li ha rotti? I test non sono stati progettati correttamente e non riescono a causa di esso?

Indipendentemente dal problema. Se la funzionalità esiste ancora, rimane E dovrebbe essere corretto per eseguire correttamente il test, anche se è necessario attendere fino a un momento successivo. (abbastanza presto questo rumore farà arrabbiare qualcuno abbastanza che faranno qualcosa a riguardo, sperando che qualcosa inizi a risolverli.)

Ora, se questa funzionalità è temporaneamente bloccata, potresti disabilitare i test fino a quando non lo rivedi.

Se la funzionalità viene rimossa (e non si prevede che ritorni mai) solo allora rimuoverò i test.

    
risposta data 02.05.2014 - 22:39
fonte
6

Non verrà corretto - perché?

È qualcosa che è pianificato per essere risolto in seguito? Mantieni i test.

L'intera funzionalità non è più rilevante (i test stanno controllando qualcosa che non è più vero)? Verifica se è possibile correggere i test per verificare la funzionalità corretta o semplicemente rimuovere i test se esistono già nuovi test per la nuova funzionalità.

    
risposta data 02.05.2014 - 22:38
fonte
5

Dovrebbe essere ovvio che non si aggiusta il codice perché un test dell'unità fallisce, ma perché il codice fa le cose sbagliate - il test unitario è solo un indicatore, e i test unitari non sono sempre per definizione sempre corretti. Se dici "il nostro codice è sbagliato ma non ci si può preoccupare di risolverlo", lascia i test unitari e subisci la vergogna. Se dici "il nostro codice è corretto, non puoi aspettarti che venga chiamato in quel modo", rimuovi il test dell'unità.

Se si scrive una funzione, si definiscono gli input legali e si definiscono gli output corretti per ciascun input, quindi un test unitario che non fornisce input legali e gli errori devono essere rimossi. Se il tuo codice è limitato dalla precisione dell'aritmetica in virgola mobile, allora un test che fallisce perché prevede una maggiore precisione dovrebbe essere rimosso. Questo è quello che sembra stia succedendo qui.

Quando ho detto "input legali", ciò potrebbe ovviamente essere frainteso. Posso scrivere una funzione che si aspetta un indirizzo email valido come input; questa funzione potrebbe non riuscire se si passa qualcosa che non è un indirizzo email valido. Posso scrivere un'altra funzione che si aspetta una stringa C non terminata da zero NULL che possa contenere qualsiasi byte ma che dovrebbe contenere un indirizzo email valido nella codifica UTF-8. Un test unitario che lo chiama con un puntatore nullo o una stringa non terminata è sbagliato e dovrebbe essere rimosso. Ma un test unitario che passa una stringa valida con dati di spazzatura dovrebbe portare a un corretto rilevamento dei dati di spazzatura, perché con la definizione della funzione qualsiasi dato di spazzatura è "input legale" che deve essere gestito correttamente (molto probabilmente identificato e un errore restituito o un'eccezione generata). Anche i casi di test che entrano nei casi d'angolo assoluti delle specifiche e si aspettano che vengano gestiti correttamente sono corretti.

    
risposta data 03.05.2014 - 01:22
fonte
3

Il problema più grande con i fastidiosi messaggi dei sistemi di manutenzione, indipendentemente dal fatto che siano test automatici, file di registro o altra fonte di informazioni è che i ricevitori di quei messaggi si attenuano al rumore e si sintonizzano.

In questo momento, puoi esaminare tre test unitari falliti e pensare: "Non è un grosso problema", ma è una pendenza scivolosa. Probabilmente non hai un corridore di test abbastanza sofisticato da "ignorare tutti, ma questi tre fallimenti" per mostrarti una barra verde, e probabilmente solo vagamente guardi " n test run, m passato, x non riuscito "quando esegui i test.

Lo scopo dei test unitari è prestare attenzione in modo da non doverlo fare. Ciò ti consente di eseguire il refactoring con la consapevolezza che i test ti diranno se hai trascurato qualcosa.

Sembra che tu pensi che il test unitario dovrebbe rimanere. In tal caso, è necessario correggere il codice in modo che il test passi, anche se è necessario iniettare una simulazione per qualche altro componente. (È un test unitario, non un test di integrazione.)

    
risposta data 03.05.2014 - 06:47
fonte
1

Direi: no! Se un test dell'unità fallito non è necessario e mostra solo piccoli bug, non dovresti rimuoverlo, perché tali test di unità sono essenziali per il plannig futuro e per la tracciabilità dei bug della tua applicazione.

Nella versione attuale il bug potrebbe non influenzare la tua applicazione, ma puoi garantire che per le versioni future in cui i requisiti cambiano?

Saluti Nico

    
risposta data 02.05.2014 - 22:32
fonte
1

La risposta ovvia è che se i comportamenti non verranno corretti, in realtà il loro comportamento effettivo non è "inatteso", ma piuttosto "atteso": è inteso essere in un in un certo modo, e si capisce perché è così, e si capisce che continuerà in quel modo (non sarà "risolto").

Tale comportamento dovrebbe essere codificato come il comportamento previsto che il test unitario convalida.

Se il passaggio di NaN a una funzione produce un falso positivo, quindi scrivere il test di regressione in modo che lo convalidi. Poi un giorno se passare NaN a quella funzione produce un negativo, qualcosa è cambiato (forse in modo spezzato).

    
risposta data 04.05.2014 - 09:27
fonte
1

C'è un continuum in cui queste situazioni cadono. Se hai bisogno della funzionalità dell'unità test, dovresti ovviamente tenerli. Se non lo userai mai più, mai, mai più, e lo sai e ne sei assolutamente, positivamente, sicuro al 100%, dovresti buttare fuori quei test unitari. Per qualsiasi altro livello di certezza, la risposta non è così semplice.

Se si utilizzerà la funzionalità, ma non in questo momento, è possibile mantenere i test dell'unità, a meno che non interferiscano con altri test di unità o con la convalida del codice. Una suite di test che ho usato, BusterJS for Node, ha un metodo per mettere "unitamente" i test unitari mettendo 2 barre davanti al nome, all'interno della sua stringa. In effetti, stai "commentando il test", anche se Buster sa ancora che è lì e ce lo mostra. La tua suite di test potrebbe avere qualcosa di simile: se ti dà fastidio, USA!

Se c'è la più piccola possibilità che tu possa mai usare la funzionalità, decidi quanto è importante che sia testato se lo usi, quanto siano intrusivi i test e quanto gonfiano, quindi decidi da lì. Tieni anche presente che tutto questo codice ha un costo in termini di leggibilità e spazio, anche se di solito ci sono modi per separarlo definitivamente dal resto del codice e probabilmente non occuperà abbastanza spazio extra di cui preoccuparsi. Le prestazioni di solito non sono un problema, in quanto l'app di solito è abbastanza intelligente da non eseguire i test mentre è in esecuzione il codice di produzione.

Infine, ricorda che potresti essere in grado di avere il meglio di entrambi i mondi: i test di unità esistono e sono mantenuti aggiornati, ma sono opzionali nella tua suite di test o non sono effettivamente eseguiti. Come lo fai dipende da te, ma la maggior parte dei linguaggi di programmazione ha un concetto chiamato "commentando". Questo è probabilmente il modo in cui stai scrivendo la tua documentazione, quindi perché non usarla per cose che ti servono o che vuoi ma che non stai usando in questo momento? Quindi, se hai mai avuto bisogno di usare il test, non rendilo più un commento. Ricordarsi di mantenere i test aggiornati come necessario o desiderato testando periodicamente i test stessi.

    
risposta data 04.05.2014 - 06:10
fonte
0

In generale si dovrebbe evitare il codice morto di tutti i tipi. Indipendentemente dalla sua produzione o codice di prova. Anche se trovi argomenti convincenti per mantenere un particolare codice, la cosa principale che gli altri sviluppatori vedono è che il codice morto è accettabile e lo faranno anche loro. E poiché potrebbero non essere consapevoli delle tue giustificazioni, lo faranno per ragioni molto meno profonde. Ed è vero che aggiungerà al rumore generale. Vedi la teoria delle finestre rotte.

Se si desidera mantenere questo codice di test guasto, solo per ricordare gli assunti che i metodi testati fanno sui parametri di input, quindi andare avanti documentare queste ipotesi per il metodo stesso! O per renderlo più esplicito puoi scrivere asserzioni esplicite nel tuo metodo, che può servire come documentazione e come strumento di debug se abilitato durante il debug. Sono disponibili persino i framework di precondizione se si desidera seguire questa strada, ma ciò non è realmente necessario.

Spesso il codice morto può essere rimosso senza sostituzione. Altre volte può ancora essere cancellato, ma dovrebbe essere sostituito con qualche documentazione o del codice reale (come le asserzioni). Se hai per mantenere il codice morto in giro, assicurati di documentare le ragioni in tal senso proprio sopra il blocco di codice incriminato.

    
risposta data 03.05.2014 - 22:35
fonte

Leggi altre domande sui tag