È ragionevole non scrivere test unitari perché tendono ad essere commentati in un secondo momento o perché i test di integrazione hanno più valore?

34

Stavo discutendo di test di unità / integrazione con un collega e ha presentato un caso interessante contro per scrivere test di unità. Sono un grande test unitario (JUnit principalmente) proponente, ma sono interessato a sentire le riprese degli altri, dato che ha fatto alcuni punti interessanti.

Per riassumere i suoi punti:

  • Quando si verificano le principali modifiche al codice (nuova serie di POJO, applicazione principale refactoring, ecc.), i test unitari tendono ad essere commentati piuttosto che rielaborato.
  • Il tempo è speso meglio per i test di integrazione che coprono casi d'uso, che rendono i test con un ambito più piccolo meno / non-per niente importanti.

Pensieri su questo? Sono ancora un pro-unit test (come vedo costantemente produrre codice migliorato), sebbene i test di integrazione suonino almeno altrettanto preziosi.

    
posta Jeff Levine 12.12.2015 - 07:01
fonte

9 risposte

60

Tendo a schierarmi con il tuo amico perché troppo spesso, i test unitari stanno testando le cose sbagliate .

I test unitari non sono intrinsecamente cattivi. Ma spesso verificano i dettagli dell'implementazione piuttosto che il flusso di input / output. Si finisce con test completamente inutili quando questo accade. La mia regola è che un buon test unitario ti dice che hai appena rotto qualcosa; un cattivo test unitario ti dice semplicemente che hai appena cambiato qualcosa.

Un esempio in cima alla mia testa è un test che è stato inserito in WordPress qualche anno fa. La funzionalità testata ruotava intorno a filtri che si chiamavano l'un l'altro, e i test stavano verificando che i callback sarebbero stati richiamati nell'ordine corretto. Ma invece di (a) eseguire la catena per verificare che i callback vengano richiamati nell'ordine previsto, i test si focalizzano su (b) leggendo alcuni stati interni che probabilmente non avrebbero dovuto essere esposti all'inizio. Cambia gli interni e (b) diventa rosso; mentre (a) diventa rosso solo se le modifiche ai componenti interni interrompono il risultato previsto mentre lo fanno. (b) è stato chiaramente un test inutile a mio avviso.

Se hai una classe che espone alcuni metodi al mondo esterno, la cosa corretta da testare nella mia vista sono gli ultimi metodi solo . Se testi il anche la logica interna, si può finire per esporre la logica interna al mondo esterno, usando metodi di test contorti, o con una litania di test unitari che invariabilmente si interrompono ogni volta che si desidera cambiare qualcosa.

Con tutto ciò che detto, sarei sorpreso se il tuo amico è critico nei test di unità di per sé come sembra suggerire. Piuttosto, mi piacerebbe capire che è pragmatico. Cioè, ha osservato che i test unitari che vengono scritti sono per lo più inutili nella pratica. Citando: "i test unitari tendono ad essere commentati piuttosto che rielaborati". Per me c'è un messaggio implicito lì - se tendono a dover rielaborare è perché tendono a succhiare. Assumendo così, segue la seconda proposizione: gli sviluppatori perderebbero meno tempo a scrivere codice più difficile da sbagliare, cioè test di integrazione.

Come tale non si tratta di uno essere meglio o peggio. È solo che uno è molto più facile da sbagliare, e anzi molto spesso sbagliato nella pratica.

    
risposta data 12.12.2015 - 14:25
fonte
38

When major code changes occur, unit tests tend to be commented out rather than reworked.

Con un gruppo indisciplinato di codificatori di cowboy che pensano che tutti i test che diventano "ecologici" siano soddisfatti quando si commentano tutti i test esistenti: ovviamente. I test delle unità di rilavorazione richiedono lo stesso livello di rigore con cui vengono scritti nella prima mano, quindi quello su cui devi lavorare qui è la "definizione di fatto" della tua squadra.

Time is better spent on integration tests covering use cases which make the smaller-scoped tests less/not-at-all important.

Non è né completamente sbagliato né completamente giusto. Lo sforzo per scrivere test di integrazione utili dipende molto dal tipo di software che si sta scrivendo. Se si dispone di un software in cui i test di integrazione possono essere scritti quasi altrettanto facilmente come test di unità, vengono eseguiti ancora in fretta e offrono una buona copertura del codice, quindi il collega ha un punto. Ma per molti sistemi ho visto che questi tre punti non possono essere facilmente soddisfatti dai test di integrazione, ecco perché dovresti sforzarti di avere anche dei test unitari.

    
risposta data 12.12.2015 - 08:01
fonte
14

Non so che accetto gli argomenti del tuo collega.

  1. Se i test unitari sono commentati, è perché qualcuno è pigro. Non è colpa dei test unitari. E se inizi a usare il pigro come scusa, puoi discutere contro qualsiasi pratica che richiede un piccolo sforzo.
  2. Se lo stai facendo bene, i test unitari non devono richiedere molto tempo. Non ti impediscono di fare lavori più importanti. Se siamo tutti d'accordo sul fatto che la risoluzione di un codice errato è più importante di ogni altra cosa, un test unitario è piuttosto dannoso. È un modo semplice per testare le condizioni del post. Senza di esso, come fai a sapere di aver soddisfatto le garanzie sulla condizione post? E se non l'hai fatto, il tuo codice è rotto.

Ci sono altri argomenti più convincenti contro i test unitari. Beh, non esattamente contro di loro. Inizia con il danno al design indotto dal test . È uno scrittore divertente, quindi leggilo. Quello che ho preso da questo:

Se apporti grandi modifiche al design per soddisfare i tuoi test unitari, potrebbero ostacolare altri obiettivi nel tuo progetto. Se possibile, chiedi a una persona imparziale quale approccio sia più facile da seguire. Se il tuo codice altamente testabile è difficile da capire, potresti perdere tutti i benefici ottenuti dai test unitari. Il sovraccarico cognitivo di troppa astrazione rallenta e rende più facili gli errori leaky. Non scartarlo.

Se vuoi essere sfumato e filosofico, ci sono molte grandi risorse:

risposta data 12.12.2015 - 07:58
fonte
6

When major code changes occur (new set of POJOs, major application refactoring, etc.), unit tests tend to be commented out rather than reworked.

Non farlo. Se trovi qualcuno che lo fa, uccidili e assicurati che non si riproducano, poiché i loro figli potrebbero ereditare quel gene difettoso. La chiave per come la vedo guardando gli spettacoli televisivi CSI è di spargere un sacco di campioni di DNA fuorvianti ovunque. In questo modo inquinerai la scena del crimine con così tanto rumore che, data la natura dispendiosa e dispendiosa in termini di tempo del test del DNA, la probabilità che la fissino a te è astronomicamente bassa.

    
risposta data 12.12.2015 - 17:11
fonte
4

unit tests tend to be commented out rather than reworked.

A quel punto il processo di revisione del codice dice "vai a riparare i test unitari" e questo non è più un problema :-) Se il tuo processo di revisione del codice non sta rilevando questo tipo di difetto principale nel codice inviato, allora questo è il problema.

    
risposta data 12.12.2015 - 09:24
fonte
3

When major code changes occur (new set of POJOs, major application refactoring, etc.), unit tests tend to be commented out rather than reworked.

Cerco sempre di mantenere separato il refactoring e il cambio di funzionalità. Quando ho bisogno di fare entrambe le cose, di solito commetto il refactoring per primo.

Quando si refactoring il codice senza modificare la funzionalità, i test di unità esistenti dovrebbero contribuire a garantire che il refactoring non rotti accidentalmente la funzionalità. Quindi, per un tale impegno, ritengo che disabilitare o rimuovere i test unitari sia un segnale di avvertimento importante. Ad ogni sviluppatore che fa ciò dovrebbe essere detto di non farlo quando il codice è in fase di revisione.

È possibile che le modifiche che non cambiano la funzionalità causino comunque il fallimento dei test unitari a causa di test unitari difettosi. Se comprendi il codice che stai modificando, la causa di tali errori di test unitari è di solito immediatamente evidente e facile da risolvere.

Ad esempio, se una funzione accetta tre argomenti, un test unitario che copre l'interazione tra i primi due argomenti per la funzione potrebbe non aver avuto cura di fornire un valore valido per il terzo argomento. Questo difetto nel test dell'unità può essere esposto da un refactoring del codice testato, ma è facile da risolvere se si capisce cosa deve fare il codice e cosa sta testando il test unitario.

Quando si cambiano le funzionalità esistenti, di solito sarà necessario anche cambiare alcuni test unitari. In questo caso i test unitari aiutano a garantire che il codice modifichi la funzionalità come previsto e non abbia effetti collaterali indesiderati.

Quando si risolvono bug o si aggiungono nuove funzionalità, in genere è necessario aggiungere più test unitari. Per quelli può essere utile impegnare prima i test unitari e commettere la correzione di bug o nuove funzionalità successivamente. Ciò rende più semplice verificare che i nuovi test di unità non siano passati con il codice precedente ma passino con il codice più recente. Questo approccio non è del tutto privo di inconvenienti, quindi esistono anche argomenti a favore del commit simultaneo sia di nuovi test di unità che di aggiornamenti di codice.

Time is better spent on integration tests covering use cases, which make the smaller-scoped tests less/not-at-all important.

C'è qualche elemento di verità in questo. Se riesci a ottenere la copertura dei livelli inferiori dello stack software con test rivolti ai livelli superiori dello stack software, i test potrebbero essere più utili durante il refactoring del codice.

Non penso che troverai un accordo sulla distinzione esatta tra un test unitario e un test di integrazione. E non mi preoccuperei se hai un caso di test che uno sviluppatore chiama un test unitario e un altro chiama un test di integrazione, purché sia d'accordo sul fatto che sia un caso di test utile.

    
risposta data 12.12.2015 - 12:13
fonte
3

Vengono eseguiti test di integrazione per verificare se il sistema si comporta come dovrebbe, il che ha sempre valore aziendale. I test unitari non sempre lo fanno. Per esempio, i test unitari potrebbero testare il codice guasto.

C'è una filosofia di test che dice che qualsiasi test che non ti dà informazioni è uno spreco. Quando un pezzo di codice non viene lavorato, i suoi test unitari sono sempre (o quasi sempre) verdi, fornendo poche o nessuna informazione.

Ogni metodo di test sarà incompleto. Anche se ottieni una copertura del 100% secondo alcuni parametri, non stai ancora analizzando quasi tutti i possibili dati di input. Quindi, non pensare che i test unitari siano magici.

Ho visto spesso affermare che avere test unitari migliora il tuo codice. A mio parere, i miglioramenti apportati dai test unitari al codice stanno costringendo le persone che non sono abituate a suddividere il loro codice in pezzi piccoli e ben fatti. Se ti abitui a progettare normalmente il tuo codice in piccoli pezzi ben fatti, potresti scoprire che non hai bisogno di test unitari per costringerti a farlo più.

A seconda di quanto pesantemente fai il test unitario e quanto è grande il tuo programma, potresti finire con un'enorme quantità di test unitari. Se è così, i grandi cambiamenti diventano più difficili. Se un grosso cambiamento causa un sacco di test unitari falliti, puoi rifiutarti di fare il cambio, fare un sacco di lavoro per risolvere molti test o buttare via i test. Nessuna delle scelte è l'ideale.

I test unitari sono uno strumento nella casella degli strumenti. Sono lì per servirti, non viceversa. Assicurati di uscirne almeno quanto hai inserito.

    
risposta data 12.12.2015 - 12:43
fonte
3

I test unitari non sono sicuramente il proiettile d'argento che alcuni sostenitori affermano di essere. Ma in generale hanno un rapporto costi / benefici molto positivo. Non renderanno il tuo codice "migliore", forse più modulare. "migliore" ha molti più fattori di ciò che implica "testabilità". Ma assicureranno che funzioni in tutti i casi e gli usi a cui hai pensato, e eliminerà la maggior parte dei tuoi bug (probabilmente quelli più banali).

Il più grande vantaggio dei test unitari è che rendono il codice più flessibile e resiliente al cambiamento. Puoi refactoring o aggiungere funzionalità ed essere abbastanza sicuro di non aver infranto nulla. Questo da solo ne vale la pena per la maggior parte dei progetti.

Riferendosi ai punti fatti dal tuo amico:

  1. Se l'aggiunta di POJO interrompe i test unitari, probabilmente sono scritti molto male. I POJO sono di solito la lingua che stai usando per parlare del tuo dominio, e i problemi che stai risolvendo, cambiarli ovviamente significa la tua intera logica aziendale e probabilmente il codice di presentazione deve cambiare. Non puoi aspettarti che cosa garantisce che quelle parti del tuo programma non cambino ...

  2. Lamentarsi che i test di Unità siano cattivi, perché la gente li commenta, è come lamentarsi che le cinture di sicurezza sono cattive perché le persone non le indossano. Se si commenta un codice di prova e si rompe qualcosa, dovrebbe finire in una conversazione molto seria e spiacevole con il suo capo ...

  3. I test di integrazione sono di gran lunga superiori ai test unitari. nessuna domanda. specialmente se stai testando un prodotto. Ma scrivere buoni test di integrazione completi, che ti daranno lo stesso valore, la copertura e la certezza della correttezza che il test unitario ti dà, è incredibilmente difficile.

risposta data 12.12.2015 - 18:40
fonte
2

Posso solo pensare ad un argomento contro i test unitari, ed è piuttosto debole.

I test unitari mostrano la maggior parte del loro valore quando si effettua il refactoring o si modifica il codice in una fase successiva. Vedrai un'enorme riduzione del tempo richiesto per aggiungere funzionalità e assicurarti di non aver rotto nulla.

Tuttavia: c'è un (piccolo) costo nel tempo di scrivere i test in primo luogo però.

Pertanto: se un progetto è abbastanza breve e non richiede manutenzione / aggiornamenti in corso, è possibile che il costo dei test di scrittura superi i loro benefici.

    
risposta data 12.12.2015 - 11:07
fonte

Leggi altre domande sui tag