Unittests sporadici o TDD?

6

Ho letto alcune nozioni di base sui test unitari e TDD, ma trovo difficile convincermi del motivo per cui TDD può avere un vantaggio rispetto alle sole selezioni selezionate.

Ho letto argomenti comuni per TDD, ma non vedo l'improvvisazione rispetto alle semplici unittests. Forse puoi aiutare a chiarire:

  • TDD consente un design testabile liberamente accoppiato - > Credo di poter benissimo immaginare se una classe sia teoricamente testabile, senza dover scrivere test; L'accoppiamento lento è un requisito fondamentale che si può giudicare senza fare riferimento a TDD?!
  • TDD dà fiducia nel refactoring - > Non è più efficiente aggiungere selezioni selezionate non appena inizi il refactoring? Mentre devi pensare a cosa coprire per test, risparmi ancora scrivendo molti test.
  • TDD ti consente di definire prima l'interfaccia - > A me sembra che alcuni punti minori siano più facili da decidere durante la codifica (che concorda anche con l'agilità?). È persino difficile prevedere una struttura di dati di ritorno annidata, ma dopo la codifica posso spesso convalidare che ottengo ciò che mi aspettavo. Ho creato i dati nidificati durante la codifica (una piccola unità) e ho visto il comportamento. Avrei risparmiato un sacco di tempo a scrivere prima il metodo e usare a posteriori il risultato convalidato per collegarlo a un unittest.
  • da quello che ho letto molte (ovviamente non tutte) fonti affermano che TDD richiede più tempo di sviluppo anche considerando il vantaggio per il debug; semplicemente migliora la qualità del codice - > Può essere che alcuni programmatori commettano diversi tipi di errori e per alcuni TDD non copre il tipo di errori che fanno comunque? Quindi, se i miei tipici bug non sono accessibili da test prevedibili, non fa per me?
  • TDD aiuta a cambiare team e team di interazione più grandi - > È un grosso problema? Posso immaginare che lo sia, ma per il momento in cui programma da solo non posso giudicare. In che modo TDD aiuta i team in modi che ... ed ecco il punto importante: altri modi no? Può imporre un po 'di disciplina ai membri meno esperti del team, ma a parte questo qualche vantaggio?
posta Gerenuk 02.08.2012 - 10:56
fonte

6 risposte

4

TDD allows a loosely coupled, testable design -> I believe I can well imagine if a class is theoretically testable, without having to write tests; Loose coupling is a fundamental requirement that one can judge without refering to TDD?!

Hai ragione TDD ti aiuta a imparare come progettare in questo modo, costringendoti a. Ma andare in bicicletta con le ruote da allenamento non è sempre necessario, è possibile progettare bene senza TDD.

TDD gives confidence in refactoring Isn't it more efficient to add selected unittests as soon as you start refactoring? While you have to think what to cover by test, you still save writing a lot of tests.

Il problema è che potresti non ricordare quali test unitari aggiungere quando rivedi i giorni del codice o mesi dopo. Potrebbe essere necessario un refactoring solo per aggiungere test unitari, rompendo le cose in modo imprevisto. Allo stesso tempo, potrebbe essere necessario ridefinire i test unitari, aumentando il sovraccarico. Oppure i test unitari possono darti falsa fiducia. È molto situazionale se il test-first o il test-after sia più efficace.

TDD makes you define the interface first - To me it seems some minor points are easier to decide while coding (which also agrees with agile?). It's even hard to predict a nested return data structure, but after coding I can often validate that I get what I expected. I made up the nested data while coding (a small unit) and see the behaviour. I'd save a lot of time writing the method first and using the validated result a posteriori to plug into a unittest.

Pensare per prima cosa richiede pratica, ma ha il vantaggio di garantire che il codice sia testabile dall'unità senza refactoring. BTW non scrive prima Interface se è quello che stai pensando, scrivi prima un'interfaccia (tutte le classi hanno un'interfaccia).

From what I've read many (of course not all) sources state that TDD does require more development time even considering the benefit for debugging; merely the code quality improves -> Can it be that some programmers make different kinds of mistakes and for some TDD doesn't cover the type of mistakes they make anyway? So if my typical bugs are not approachable by predictable tests, it's not for me?

Il TDD può impiegare molto meno tempo del normale, ma è necessario esercitarlo a sufficienza e imparare quali sono i test più efficaci. Fai puro TDD su un progetto per animali domestici per vedere com'è, ma non fare il puro TDD ovunque: è una perdita di tempo. Invece applica la tua abilità TDD in modo selettivo (mix di mano / unità / test di integrazione alcuni test-prima alcuni dopo), anche questo richiede esperienza.

TDD aids changing teams, and larger interacting teams - Is this a large issue? I can imagine it is, however as for the moment I program alone I cannot judge. How does TDD help teams in ways that... and here is the important point: other ways don't? It can force some discipline for less experienced team members, but apart from that any advantages?

TDD impiega molto tempo per imparare e invierà un progetto in picchiata se lo applichi a una squadra che non lo conosce affatto.

    
risposta data 02.08.2012 - 16:07
fonte
10

Potresti pensare che il tuo design sia liberamente accoppiato e ben utilizzabile. Potresti anche aver ragione, se sei davvero, davvero bravo a progettare. Il problema è che molte persone pensano di essere dei grandi designer, e alcuni di loro, in realtà, non lo sono. TDD ti obbliga a dimostrare che il design ha le proprietà che pensi di avere, proprio come test in generale ti costringe a dimostrare (approssimativamente, non formalmente) che il codice è corretto , piuttosto che assumere è corretto.

Informazioni sul refactoring: è possibile aggiungere test unitari se e quando si refactoring, e in effetti questo è esattamente ciò che è suggerito per lavorare con il codice legacy. Tuttavia, una volta che sei nel punto in cui devi rifattorizzare un gran casino di codice, hai quasi certamente dimenticato i dettagli, i casi limite, le sfumature semantiche di certi valori ecc. Ecc. Che dovresti essere stati correttamente documentato, ma non lo era. Ancora una volta, i test unitari esistenti già catturano questa conoscenza dettagliata, motivo per cui scriverli in anticipo è meglio che scriverli in ritardo. Un test scritto immediatamente prima del refactoring è molto meno probabile che test effettivamente ciò che dovrebbe testare.

Il punto tre sembra essere un misto di altri punti e alcune cose che in realtà non capisco, quindi: non lo so.

Punto quattro: non credo che sia possibile avere un pregiudizio verso i "tipici bug" che non sono rilevabili dai test. Cosa sarebbero quelli? Certo, ci sono problemi che sono molto più difficili da testare rispetto ad altri problemi, come problemi che possono verificarsi solo in situazioni di integrazione estreme (es. Live con milioni di utenti contemporaneamente), ma qualcuno dovrebbe davvero avere un talento per scrivere codice corretto tranne in tali situazioni? Sembra improbabile per me.

I cambiamenti nello staff sono sicuramente un grosso problema: più grande è l'organizzazione, più grande diventa un problema, ma anche se si programma da solo, la persona che guarda il codice tra un anno e l'altro si chiede "quale idiota ha programmato quello? ?" è molto diverso da chi lo ha effettivamente scritto - anche se tecnicamente sono la stessa persona. Questo mi succede tutto il tempo. Un test unitario ti dà la possibilità di capire perché e in che modo il sistema non funziona come hai pensato.

Nel complesso, quindi, il punto veramente importante (per me) è scrivere i test mentre continui a capire completamente il sistema e con una copertura il più possibile vicina al 100% . Se scriverete o meno ogni test un minuto prima di scrivere una routine o un minuto dopo è in realtà un po 'meno importante.

    
risposta data 02.08.2012 - 11:16
fonte
2

Parliamo prima di tutto di punti diversi: che cosa intendi per "semplice test unitario"? Scriveresti un test solo per percorso felice? Solo i metodi che pensi potrebbero rompere? È difficile dire quello che hai in mente, ma per il resto di questo post presumo che tu scriverà solo alcuni test in cui ritieni che siano utili, invece di fare una copertura da vicino a completo come sarebbe il TDD.

Poche note ai tuoi punti:

  • TDD ti permette di definire prima l'interfaccia: non è davvero un argomento per TDD, dato che puoi definire prima l'interfaccia senza di essa. Ciò che invece fa TDD, ti consente di concentrarti sui dettagli di alto livello del pezzo su cui stai lavorando in un dato momento, senza essere disturbato dall'immersione profonda nelle dipendenze. Ma poi di nuovo, questo non è specifico per TDD.
  • TDD richiede più tempo anche considerando i vantaggi del debug: questo è vero, semplicemente perché in TDD si scrive più codice. Il vantaggio indiretto è che, grazie al fatto che avrai una copertura molto migliore rispetto all'approccio "test unitario sporadico", regressione sarà meno doloroso.
  • "se i miei tipici bug non sono accessibili dai test prevedibili (...)": è davvero un bug quando lo si conosce in anticipo e si scrive codice per prevenirlo prima che accada realmente?

Penso che tu stia confrontando approcci errati. TDD vs "test di unità sporadiche", mentre dovrebbe essere test completo rispetto a test sporadici . TDD risulterà in test completo , ma è possibile ottenere ciò anche senza TDD.

Devi decidere in che misura consideri la copertura del codice decente (non quella deludente magico-fiaba 100%) rispetto alla copertura "alcuni"; Il tempo speso per scrivere un codice di prova extra rispetto al tempo guadagnato quando i test effettivamente aiutano a scoprire e correggere i bug relativi alla regressione, poiché questo sarà il loro principale vantaggio rispetto agli approcci no-test.

    
risposta data 02.08.2012 - 11:56
fonte
1

Una cosa importante che ho imparato la scorsa settimana riguardo a TDD è che è qualcosa di diverso rispetto a scrivere solo i test. Il principale vantaggio di TDD come principio di progettazione è che ti fa pensare a ciò di cui hai bisogno quando ne hai bisogno (il YAGNI principio).

Letture interessanti:

risposta data 13.08.2012 - 16:09
fonte
0

Per prima cosa ho iniziato a creare test unitari per dove pensavo fosse necessario. Per renderlo peggio soprattutto l'ho fatto dopo aver scritto il codice da testare.

Il fatto che io potrei scegliere cosa testare potrei (non sono una persona strong che puoi dire) tralasciare parti di codice importanti / rischiose perché ho detto: sì, questo non è mai ha rotto .

Il fatto di aver scritto i test dopo il codice ha reso difficile la verifica del mio codice. Non era basato su unità, ma piuttosto una raccolta di hack (che può essere semplicemente perché non ho talento).

Una volta avviato TDD

  • Non potrei mai tralasciare roba (o molto meno probabile) dai test
  • Ho scritto solo il codice che era veramente necessario
  • Il mio codice era ben strutturato (o almeno meglio).

Buon codice!

    
risposta data 13.08.2012 - 17:49
fonte
0

Spesso scrivo test unitari ma penso che, come ogni strumento, non sono la soluzione per tutti i problemi e si dovrebbe valutare caso per caso se sono appropriati o meno. Usarli sistematicamente per ogni pezzo di codice che scrivo non mi sembra la soluzione più efficace per me.

Ecco alcune situazioni in cui i test di unità si sono dimostrati molto utili per me:

  • Convalida i metodi che eseguono trasformazioni complesse dei dati: test delle unità con molti input e output possibili mi hanno permesso di scoprire anche piccoli bug molto presto.
  • Refactoring: i test unitari aiutano a garantire che il codice refactored abbia la stessa funzionalità del codice originale. I bug appena introdotti appaiono molto presto.

D'altra parte, ho alcuni dubbi riguardo a TDD e se questo approccio è sempre il migliore. Ecco alcuni punti critici:

Non tutto il codice può trarre profitto dai test unitari, ad es. supponiamo di voler verificare che un determinato evento venga inviato al componente corretto nella GUI. La cosa più efficace da fare è eseguire il programma e, ad esempio, controllare che il pulsante appropriato sia abilitato. Lo sforzo necessario per testare unitariamente la logica sottostante sarebbe troppo alto rispetto ai test manuali che (almeno se hai un processo di sviluppo decente) lo eseguirai comunque.

A volte sviluppo classi interrelate come cluster e non sono sicuro di quali classi e metodi ho veramente bisogno fino a quando l'intero cluster di classi non è finito. Un tale ciclo può durare alcuni giorni. Durante questo ciclo posso introdurre nuove classi e poi, a un secondo pensiero, rendermi conto che non ho bisogno di loro e rimuoverle. Se avessi scritto test unitari per queste classi, avrei dovuto buttare via anche i test unitari. Quindi trovo molto più efficiente scrivere (1) unit test per classi critiche selezionate e (2) iniziare a scrivere i test unitari verso la fine di un ciclo di sviluppo (di pochi giorni) quando la struttura di classe si è stabilizzata abbastanza, quindi che non sprecare il mio tempo a scrivere test unitari che ho intenzione di buttare via più tardi.

    
risposta data 15.08.2012 - 12:48
fonte

Leggi altre domande sui tag