2010-08-08 12 views
7

Quindi mi sto abituando a TDD, ma mi sono imbattuto in un problema inaspettato: mi sto davvero stancando della copertura del 100% del codice. I test stanno diventando sempre più noiosi da scrivere rispetto al codice stesso, e non sono sicuro che lo stia facendo bene. La mia domanda è: Che tipo di cose dovresti testare e che tipo di cose sono esagerate?Affrontare TDD/unità Test di affaticamento

Ad esempio, ho un test come segue, e non sono sicuro se è utile a tutti. Cosa dovrei fare per seguire ancora TDD ma non mi stanco di scrivere test?

describe 'PluginClass' 

    describe '.init(id, type, channels, version, additionalInfo, functionSource, isStub)' 

     it 'should return a Plugin object with correct fields' 

      // Create test sets 
      var testSets = new TestSets() 
      var pluginData = { 
       'id'    : null, 
       'type'    : null, 
       'channels'   : null, 
       'version'   : null, 
       'additionalInfo' : null, 
       'functionSource' : null, 
       'isStub'   : true 
      } 
      testSets.addSet({ 'pluginData' : pluginData }) 
      var pluginData = { 
       'id'    : "testPlugin1", 
       'type'    : "scanner", 
       'channels'   : ['channelA', 'channelB'], 
       'version'   : "1.0", 
       'additionalInfo' : {'test' : "testing"}, 
       'functionSource' : "function() {alert('hi')}", 
       'isStub'   : false 
      } 
      testSets.addSet({ 'pluginData' : pluginData }) 

      for (var t = 0; t < testSets.getSets().length; t ++) { 
       var aTestSet = testSets.getSet(t) 

       var plugin = new Plugin().init(aTestSet.pluginData.id, 
               aTestSet.pluginData.type, 
               aTestSet.pluginData.channels, 
               aTestSet.pluginData.version, 
               aTestSet.pluginData.additionalInfo, 
               aTestSet.pluginData.functionSource, 
               aTestSet.pluginData.isStub ) 

       plugin.getID().should.eql aTestSet.pluginData.id 
       plugin.getType().should.eql aTestSet.pluginData.type 
       plugin.getChannels().should.eql aTestSet.pluginData.channels 
       plugin.getVersion().should.eql aTestSet.pluginData.version 
       plugin.getAdditionalInfo().should.eql aTestSet.pluginData.additionalInfo 
       eval("fn = " + aTestSet.pluginData.functionSource) 
       JSON.stringify(plugin.getFunction()).should.eql JSON.stringify(fn) 
       plugin.getIsStub().should.eql aTestSet.pluginData.isStub 
      } 

     end 

    end 

end 
+0

IMO, questo è un test di accettazione. – Gutzofter

risposta

7

Certamente il "test" sopra riportato è eccessivo per molti aspetti. È troppo lungo e complicato, difficilmente leggibile e afferma troppe cose. Riesco a malapena a immaginare come possa essere emerso da un processo TDD. Non è sorprendente che ti stanchi di cose del genere ...

Sviluppo guidato dal test: dovresti andare a piccoli passi, dove ogni passo è un test separato, asserisce solo una cosa e non contiene assolutamente alcuna logica (ovvero no for, if/else o simili ...). Quindi il codice sopra risulterebbe in circa 4-6 metodi di test separati, che poi implementeresti uno per uno. In primo luogo asserisci la corretta inizializzazione della proprietà (con valori diversi come richiesto), quindi assicurati che i metodi funzionino come previsto, e così via ...

La metrica di copertura del codice non ti dice nulla sui tuoi test eccetto che può mostrare tu il codice di produzione che non viene toccato da nessun test. Soprattutto non ti dice se il codice toccato è realmente testato (e non solo toccato ...). Questo dipende solo dalla qualità dei tuoi test. Quindi non prendi troppo seriamente la copertura del codice, ci sono molti casi in cui una copertura più bassa con test migliori è molto più preferibile ...

In somma: Non è eccessivo avere test per quasi tutto (100% copertura), ma certamente è un problema avere test come nel tuo esempio.

vi consiglio di rivedere il vostro TDD/unità pratica test, The Art Of Unit Testing libro potrebbe essere una buona risorsa ...

HTH!
Thomas

+0

+1 per raccomandare * The Art of Unit Testing * - è un ottimo libro che dà davvero buoni consigli. – Bevan

1

L'obiettivo del test dell'unità dovrebbe essere quello di testare le parti del codice che possono contenere bug. Raggiungere una copertura di prova del 100% non dovrebbe essere un obiettivo, e AFAIK, TDD non lo chiama come obiettivo.

Creare test esaurienti per codice che è improbabile che contenga errori significativi è una noiosa perdita di tempo sia ora che il sistema si evolve. (In futuro, i test di unità duplicazione sono suscettibili di essere una fonte di regressioni senza senso nei test stessi che proprio perdere tempo a qualcuno per trovare e correggere.)

Infine, voi e la vostra gestione dovrebbe sempre usare buonsenso quando applicare una metodologia di sviluppo a un progetto. Nessuna metodologia mai inventata sarà perfetta per tutti i problemi/progetti. Parte del tuo lavoro è individuare le situazioni in cui la metodologia non funziona in modo ottimale ... e, se necessario, adattarla o addirittura abbandonarla. E in questo caso, il fatto che il tuo progetto utilizzi TDD ti sta facendo impazzire è un segno chiaro che qualcosa non va bene.

+0

"Copertura di prova del 100% ... TDD non lo chiama come un obiettivo". In realtà, nella sua forma religiosa TDD richiede test scritti prima di qualsiasi linea di codice live. Altrimenti d'accordo. – KolA

+0

Leggi questo: http://agiledata.org/essays/tdd.html#Misconceptions –

3

Una cosa che penso che le persone dimentichino è che con i test di unità automatizzate, è ancora una pratica di codifica.È perfettamente accettabile impostare classi basate su modelli/generici, classi base, classi helper o qualsiasi altro normale modello di sviluppo del software a cui sei abituato per eseguire il test dell'unità. Se ti senti come se stessi facendo la stessa cosa più e più volte, probabilmente lo sei! È un segno che il tuo cervello ti sta dicendo: "C'è un modo migliore".

Quindi prendilo.

+1

molto vero. di solito questo è un segno che c'è qualcosa che non va da qualche parte. – obelix

0

Sembra che sei

  • costruttori di test con semplice assegnazione membro. Questo è eccessivo se non c'è qualche logica non banale nel costruttore. Fidatevi invece di questo per essere testati come parte di altri test in cui i membri verrebbero utilizzati.
  • confrontando l'uguaglianza tra 2 oggetti valore. Ridefinisci/definisci il controllo di uguaglianza sul tipo/classe del plugin, sovrascrivendo il metodo equals. quindi plugin.should.eql expected_plugin dovrebbe essere il solitario asserire
  • considerare anche l'uso di oggetti helper per costruire dati di test complessi.
1

Il test sta tentando di verificare troppe cose contemporaneamente. Suddividilo in diversi test e rifatta il tuo codice di test (sì, i metodi di supporto sono permessi).

Inoltre, ho l'impressione che anche il codice sotto test faccia troppo. Disaccoppiare il codice (refactor usando Extract Class e Extract Method ecc.) E testare ciascun codice di produzione in isolamento. Scoprirai che questi test diventeranno sempre meno, più semplici e più facili da leggere e scrivere.

0

Stanchezza, pigrizia e apatia sono il nostro istinto naturale per evitare lavori inutili, come la scrittura di test banali, che è probabilmente il caso. Cerca di fermare i banali test unitari e dovresti sentirti subito meglio.

Il tuo test particolare non è complicato. Sono stato coinvolto come revisore del codice in molti progetti con migliaia di test di unità e integrazione e ancora per vedere un progetto in cui i test sarebbero più facili da leggere e capire rispetto al codice reale. Leggibilità del TDD, "prova come documentazione" e quel tipo di promesse semplicemente non sono vere. È facile provare: prova ad apprendere il nuovo codice base leggendo solo i test o leggendo solo il codice live. In che modo è più completo? Il codice live correttamente progettato fornisce un'immagine completa e olistica del componente, mentre i test sono asserzioni frammentarie su di esso.

L'unico vantaggio dei test è automazione - alcune verifiche extra del codice che non è necessario eseguire manualmente/che non possono essere eseguite dal compilatore o dall'analisi del codice. Periodo. E questo vantaggio ha un costo significativo: la scrittura e la manutenzione dei test, quindi scegli attentamente cosa testare.

Problemi correlati