I test unitari sono davvero così utili? [chiuso]


98

Mi sono appena laureato in CS e attualmente ho un lavoro come sviluppatore Junior .NET (C #, ASP.NET e moduli web). Quando ero ancora all'università, l'argomento dei test unitari veniva trattato ma non ne ho mai visto i benefici. Capisco cosa dovrebbe fare, vale a dire, determinare se un blocco di codice è adatto o meno per l'uso. Tuttavia, in realtà non ho mai dovuto scrivere un test unitario prima, né ne ho mai sentito il bisogno.

Come ho già detto, di solito sto sviluppando con i moduli Web ASP.NET e recentemente ho pensato di scrivere alcuni test unitari. Ma ho alcune domande a riguardo.

Ho letto che i test unitari spesso avvengono scrivendo "mock". Anche se capisco questo concetto, non riesco a capire come dovrei scrivere simulazioni per siti Web completamente dinamici e dove quasi tutto dipende dai dati che provengono da un database. Ad esempio: utilizzo molti ripetitori con eventi ItemDataBound ecc. (Sempre a seconda dei dati "sconosciuti").

Quindi domanda numero 1: scrivere unità test per i moduli Web ASP.NET è qualcosa che viene fatto spesso, e se lo è: come posso risolvere il problema "ambiente dinamico"?

Quando sto sviluppando, passo attraverso molti tentativi ed errori. Ciò non significa che non so cosa sto facendo, ma intendo che di solito scrivo un po 'di codice, premo Ctrl F5e vedo cosa succede. Mentre questo approccio fa il lavoro per la maggior parte del tempo, a volte ho la sensazione di essere un po 'all'oscuro (a causa della mia piccola esperienza). A volte spreco molto tempo anche in questo modo.

Quindi, domanda numero 2: mi consigliereste di iniziare a scrivere test unitari? Penso che potrebbe aiutarmi nell'attuazione effettiva, ma poi di nuovo mi sento come se potesse rallentarmi.


1
Vorrei solo dire che l'altro lato è che alcuni posti li richiedono come pratica. Sono in un posto ora che non ci è permesso di fare il check-in del codice a meno che non sia coperto da unit test. Quindi è un punto notare che anche se potresti non crederci, ti potrebbe essere richiesto di farlo lungo la strada. Penso che sia un'abilità utile da imparare e avere nel tuo arsenale. Molte volte troverò piccoli errori e contrattempi nel mio codice da fare i test, quasi una piccola sessione di QA con te stesso.
Adam,

9
Come hai coperto esattamente i test unitari senza scrivere alcun test unitario? Questa era una di quelle scuole "vota te stesso" o "progetta il tuo curriculum"?
JeffO,

4
I test unitari sono discutibili - Ottimo per i linguaggi dinamici, meno utile quanto più rigorosa è la tua lingua, ma FARE PROVE. Non devono essere test unitari, ma in realtà dovresti avere test di integrazione che puoi eseguire con JUnit, sono molto utili.
Bill K,

13
-1 Siamo spiacenti, sono tutti d'accordo per buoni argomenti, anche se non sono d'accordo, ma è solo sbagliato. Nessuno afferma che "i test unitari sono per la cattura di bug nel nuovo codice", quindi è una maniaca - i test unitari sono per la cattura di regressioni . E la citazione di Dijkstra è presa fuori dal contesto - il contesto è che il test è inutile se si dispone di una specifica formale del problema .
sleske,

9
"i test unitari sono per rilevare le regressioni". No. I test automatizzati servono per rilevare le regressioni. Le regressioni richiedono invariabilmente l'esecuzione degli stessi test centinaia di volte, quindi vale la pena di automatizzarli. Sfortunatamente molte delle risposte e dei commenti su questa domanda stanno davvero affrontando il problema "I test automatici sono così utili?". I test unitari possono essere una forma di test automatizzato ma hanno un focus completamente diverso. Ritengo certamente che i test automatici valgano il loro peso in oro, ma ciò non dovrebbe essere usato come argomento per giustificare i test unitari (o TDD del resto).
njr101,

Risposte:


124

Secondo me: sì, e sì, dovresti.

  1. Ti danno fiducia nelle modifiche apportate (tutto il resto funziona ancora). Questa sicurezza è ciò di cui hai bisogno per modellare il codice, altrimenti potresti aver paura di cambiare le cose.

  2. Rendono il tuo codice migliore; la maggior parte degli errori semplici vengono colti in anticipo con i test unitari. La cattura precoce dei bug e la loro correzione è sempre più economica che risolverli in seguito, ad esempio quando l'applicazione è in produzione.

  3. Servono come documentazione per altri sviluppatori su come funziona il tuo codice e su come usarlo.

Il primo problema che affronti è che ASP.NET in sé non ti aiuta a scrivere test unitari, in realtà funziona contro di te. Se hai qualche scelta, inizia a utilizzare ASP.NET MVC , che è stato creato pensando ai test unitari. Se non è possibile utilizzare ASP.NET MVC, è necessario utilizzare il modello MVP in ASP.NET in modo da poter almeno testare facilmente la logica.

Oltre a ciò, devi solo acquisire competenza nello scrivere test unitari. Se pratichi TDD, il tuo codice viene creato testabile, in altre parole, bello e pulito.

Ti consiglierei di esercitarti e di accoppiare il programma. Mentre leggo:

Oppure, per una prima panoramica:


4
Avendo appena iniziato il test unitario, dovrei essere d'accordo. Non solo è una buona abitudine e molto utile combinato con un approccio TDD, ma riduce al minimo così tanto tempo. Non penso che i miei progetti potrebbero essere utili se non fossi in grado di eseguire un unit test e verificare che tutto funzioni correttamente anche dopo aver aggiunto una nuova funzionalità o corretto un bug. Non riesco a pensare di fare test di regressione in nessun altro modo.
kwelch,

21
Se i test unitari funzionano come documentazione, c'è qualcosa che non va. Leggere 500 righe di codice per capire come funzionano 5 righe di codice al contrario.
Coder

4
@Coder: quando si testano metodi di livello superiore, coinvolge molto più di 5 righe di codice.

7
@coder: la documentazione di una classe indica i servizi forniti dalle istanze della classe. Fornisce meno informazioni su come vengono utilizzate le istanze di questa classe nel contesto più ampio, ovvero l'interazione tra oggetti. I test ti danno il tipico codice di interazione in alcuni casi, che è stato prezioso come punto di partenza così tante volte che non riesco nemmeno a contarli.
Stefano Borini,

21
@Coder: non sta documentando cosa fa il codice, sta documentando le ipotesi inerenti a quel codice, cioè perché e quando dovrebbe funzionare. Se le ipotesi sottostanti sono invalidate da una modifica al SUT, uno o più test unitari dovrebbero fallire. Ciò non sostituisce la documentazione di progettazione / architettura di livello superiore, né i documenti XML, ma copre ciò che queste cose non potranno mai.
Aaronaught il

95

No.

Il concetto alla base dei test unitari si basa su una premessa che era nota per essere falsa da prima che fosse mai inventato il test unitario: l'idea che i test possano dimostrare che il codice è corretto.

Avere molti test che tutti superano dimostra una cosa e solo una cosa: che hai molti test che tutti superano. Non dimostra che ciò che i test stanno testando corrisponda alle specifiche. Non dimostra che il tuo codice sia privo di errori che non hai mai considerato quando hai scritto i test. (E le cose che hai pensato di testare erano i possibili problemi su cui ti stavi concentrando, quindi è probabile che tu li abbia risolti comunque!) E, ultimo ma non meno importante, non prova che i test, che sono codici stessi, sono privi di bug. (Segui l'ultimo fino alla sua logica conclusione e finirai con le tartarughe fino in fondo .)

Djikstra ha abbandonato il concetto di test come prova di correttezza già nel 1988, e ciò che ha scritto rimane altrettanto valido oggi:

Sono ormai passati due decenni da quando è stato sottolineato che i test del programma possono dimostrare in modo convincente la presenza di bug, ma non possono mai dimostrare la loro assenza. Dopo aver citato devotamente questa osservazione ben pubblicizzata, l'ingegnere del software ritorna all'ordine del giorno e continua a perfezionare le sue strategie di test, proprio come l'alchimista di un tempo, che ha continuato a perfezionare le sue purificazioni crisocosmiche.

L'altro problema con i test unitari è che crea un accoppiamento stretto tra il codice e la suite di test. Quando cambi codice, ti aspetteresti che vengano visualizzati alcuni bug che rompano alcuni test. Ma se stai modificando il codice perché i requisiti stessi sono cambiati, otterrai molti test falliti e dovrai passare manualmente su ciascuno di essi e decidere se il test è ancora valido. (Ed è anche possibile, anche se meno comune, che un test esistente che dovrebbe essere non valido passerà ancora perché hai dimenticato di cambiare qualcosa che doveva essere cambiato.)

Il test unitario è solo l'ultimo di una lunga serie di mode di sviluppo che promettono di semplificare la scrittura di codice funzionante senza essere un buon programmatore. Nessuno di loro è mai riuscito a mantenere la promessa, e nemmeno questa. Semplicemente non esiste un collegamento per sapere effettivamente come scrivere il codice di lavoro .

Vi sono alcune segnalazioni di test automatici realmente utili nei casi in cui stabilità e affidabilità sono di fondamentale importanza. Ad esempio, il progetto del database SQLite. Ma ciò che serve per raggiungere il loro livello di affidabilità è altamente antieconomico per la maggior parte dei progetti: un rapporto test-reale-codice SQLite di quasi 1200: 1. La maggior parte dei progetti non può permetterselo e comunque non ne ha bisogno.


69
Dimostra che il tuo codice si comporta correttamente per quei test. È davvero terrificante se me lo chiedi.
Stefano Borini,

111
Chi oggi crede davvero che i test unitari siano "prova di correttezza"? Nessuno dovrebbe pensarlo. Hai ragione nel dimostrare che superano solo quei test, ma questo è un punto dati in più di quello che avevi prima di scrivere i test unitari. Hai bisogno di test su molti livelli diversi per darti un'idea della qualità del tuo codice. I test unitari non dimostrano che il tuo codice sia privo di difetti, ma aumentano la tua sicurezza (o dovrebbero ...) che il codice fa quello per cui lo hai progettato e continua a fare domani quello che fa oggi.
Bryan Oakley,

40
> but if the test itself is buggy, then you have false confidencee se il tester manuale non esegue correttamente il proprio lavoro, si ha anche una falsa fiducia.
Stefano Borini,

33
@MasonWheeler: scusa, Mason, non ne sono convinto. In più di un paio di decenni di programmazione non credo di aver mai visto personalmente un caso in cui un test ha dato un falso senso di sicurezza. Forse alcuni lo hanno fatto e li abbiamo riparati, ma il costo di questi test unitari non ha superato gli enormi vantaggi di averli. Se sei in grado di scrivere codice senza testarlo a livello di unità, sono impressionato, ma la stragrande maggioranza dei programmatori là fuori non è in grado di farlo in modo coerente.
Bryan Oakley,

41
Se hai scritto un test con errori che ha superato il tuo codice, probabilmente anche il tuo codice è difettoso. Le probabilità di scrivere codice buggy e un test buggy sono molto meno del solo codice buggy. I test unitari non sono una panacea. Sono un buon livello extra (dove prudente) per ridurre l'onere per i tester manuali.
Telastyn,

60

Se hai mai visto il vantaggio di scrivere un metodo principale per testare un piccolo pezzo di codice per la scuola, il test unitario è la versione professionale / aziendale di quella stessa pratica.

Immagina anche il sovraccarico di costruire il codice, avviare il tuo server web locale, navigare nella pagina in questione, inserire i dati o impostare l'input sul seme di test corretto, inviare il modulo e analizzare i risultati ... il pulsante nUnit run.

Ecco anche un'immagine divertente ... inserisci qui la descrizione dell'immagine

Ho trovato questa immagine qui:
http://www.howtogeek.com/102420/geeks-versus-non-geeks-when-doing-repetitive-tasks-funny-chart/


2
Si, puoi. Isolare il livello Web nei test unitari per testare la configurazione Web (URL, convalida input, ecc.). Stubbing i livelli Web e database è possibile testare il livello aziendale senza un database o un server Web. Uso dbunit per testare il mio DB. Se lo desideri, puoi ancora eseguire test di integrazione completi, ma lo faccio come compito specifico dopo lo sviluppo.
Heath Lilley,

12
Grafica carina, ma la scala è gravemente sbagliata. Come ho sottolineato nella mia risposta, la copertura completa dei test di SQLite richiede circa 1200 volte più codice nei test rispetto al codice effettivo nel prodotto stesso. E anche se non sei così ossessivo riguardo alla copertura completa, hai ancora bisogno di test più volte rispetto al prodotto per avvicinarti a qualsiasi livello utile di copertura nei tuoi test. Per essere precisi qui, la parte verticale di quella linea rossa dovrebbe continuare ad andare su e su per circa 3 lunghezze di pagina.
Mason Wheeler,

27
@MasonWheeler Questo è un bel cavallo che stai battendo, penso che potrebbe essere morto però ... SQLite ha molti test perché è un dannato database. Voglio assicurarmi che funzioni. Come altro esempio, il framework Silverstripe ha quasi un rapporto 1: 1 di test: codice, quindi non è che SQLite sia rappresentativo.
Presa il

15
@MasonWheeler Stai fallendo nel primo dei paradossi di Zenone . Se vuoi ridimensionare questa immagine al livello di test di SQLite, l'asse X dovrà espandere anche qualcosa come 100 volte la sua lunghezza attuale.
Izkata,

2
Ciò è particolarmente vero quando sei uno sviluppatore di backend che non ha il tempo di iniziare a creare una pagina Web in bianco e nero solo per poter testare la logica del back-end. Tutto quello che devo fare è fornire richieste simulate e oggetti sessione ed eseguire i miei controller attraverso un test unitario, e alla fine di tutto ciò che so se è giusto o sbagliato. Se si utilizza DI, è sufficiente iniettare un DAO che interagisce con un database in memoria in modo che il database non cambi o semplicemente lanciare Exceptione catturarlo in modo che i dati non vengano impegnati. Dico SÌ ai test unitari.
Varun Achar,

49

I test unitari hanno qualcosa di misterioso al giorno d'oggi. Le persone lo trattano come se la copertura del test al 100% fosse un santo graal e come se il test unitario fosse l'unico vero modo di sviluppare software.

Manca il punto.

Il test unitario non è la risposta. Il test è.

Ora, ogni volta che sorge questa discussione, qualcuno (spesso anche io) traccerà la citazione di Dijkstra: "I test del programma possono dimostrare la presenza di bug, ma mai dimostrare la loro assenza". Dijkstra ha ragione: i test non sono sufficienti per dimostrare che il software funziona come previsto. Ma è necessario : a un certo livello, deve essere possibile dimostrare che il software sta facendo quello che vuoi.

Molte persone testano a mano. Anche gli appassionati di TDD faranno test manuali, anche se a volte non lo ammetteranno. Non può essere aiutato: poco prima di entrare nella sala conferenze per dimostrare il tuo software al tuo cliente / capo / investitori / ecc., Lo attraverserai a mano per assicurarti che funzioni. Non c'è niente di sbagliato in questo, e in effetti sarebbe folle solo aspettarsi di tutto per andare senza problemi, senza che l'attraversa manualmente - cioè, testarlo - anche se si dispone di una copertura unit test al 100% e la massima fiducia nei test .

Ma i test manuali, anche se necessari per la creazione di software, raramente sono sufficienti . Perché? Perché i test manuali sono noiosi, dispendiosi in termini di tempo ed eseguiti da esseri umani. E gli umani sono notoriamente cattivi nell'esecuzione di compiti noiosi e dispendiosi in termini di tempo: evitano di farli quando possibile e spesso non li fanno bene quando sono costretti a farlo.

Le macchine , d'altra parte, sono eccellenti nell'esecuzione di compiti noiosi e che richiedono tempo. Questo è ciò per cui i computer sono stati inventati, dopo tutto.

Pertanto, i test sono cruciali e i test automatici sono l'unico modo ragionevole per garantire che i test vengano utilizzati in modo coerente. Ed è importante testare e ripetere il test, poiché il software è sviluppato. Un'altra risposta qui rileva l'importanza dei test di regressione . A causa della complessità dei sistemi software, le modifiche spesso apparentemente innocue a una parte del sistema causano cambiamenti non intenzionali (ad esempio bug) in altre parti del sistema. Non è possibile scoprire queste modifiche indesiderate senza una qualche forma di test. E se vuoi avere dati affidabili sui tuoi test, devi eseguire i tuoi test in modo sistematico, il che significa che devi avere un qualche tipo di sistema di test automatizzato.

Cosa c'entra tutto questo con i test unitari? Bene, per la loro natura, i test unitari vengono eseguiti dalla macchina, non da un essere umano. Pertanto, molte persone hanno la falsa impressione che il test automatizzato sia uguale al test unitario . Ma non è vero: i test unitari sono solo test automatizzati di dimensioni molto ridotte .

Ora, qual è il valore nei test automatici extra piccoli ? Il vantaggio è che testano i componenti di un sistema software in modo isolato , il che consente un targeting più preciso dei test e aiuta il debug . Ma test unitari non significa intrinsecamente test di qualità superiore . Spesso conduce a test di qualità più elevata, grazie alla copertura di software con un livello di dettaglio più fine. Ma è possibile testare completamente il comportamento solo di un sistema completo, e non delle sue parti composite, e comunque testarlo a fondo.

Ma anche con una copertura del test unitario del 100%, un sistema potrebbe non essere ancora completamente testato. Perché i singoli componenti possono funzionare perfettamente in modo isolato, ma comunque fallire se usati insieme. Quindi i test unitari, sebbene estremamente utili, non sono sufficienti per garantire che il software funzioni come previsto. In effetti, molti sviluppatori integrano i test unitari con test di integrazione automatizzati, test funzionali automatizzati e test manuali.

Se non vedi valore nei test unitari, forse il modo migliore per iniziare è utilizzare un diverso tipo di test automatico. In un ambiente Web, l'utilizzo di uno strumento di test di automazione del browser come Selenium offre spesso una grande vittoria per un investimento relativamente piccolo. Dopo aver immerso le dita dei piedi nell'acqua, sarai più facilmente in grado di vedere quanto sono utili i test automatizzati. E una volta che hai i test automatizzati, i test unitari hanno molto più senso, dal momento che fornisce un turnaround più veloce rispetto ai grandi test di integrazione o end-to-end, poiché puoi indirizzare i test solo al componente su cui stai attualmente lavorando.

TL; DR: non preoccuparti ancora dei test unitari . Preoccupati solo di testare prima il tuo software.


Anche i test unitari sono scritti da umani e potrebbero essere sbagliati.
Seun Osewa,

41

Dipende

Questa è una risposta che vedrai molto quando si tratta di sviluppo del software, ma l'utilità dei test unitari dipende davvero da quanto bene sono scritti. Un numero nominale di unit test che verificano la funzionalità dell'applicazione per i test di regressione può essere abbastanza utile; tuttavia, numerosi test semplici che controllano i ritorni delle funzioni possono essere del tutto inutili e fornire un falso senso di sicurezza perché l'applicazione "ha molti test unitari".

Inoltre, il tuo tempo come sviluppatore è prezioso e il tempo speso per scrivere test unitari non è tempo impiegato per scrivere nuove funzionalità. Ancora una volta, questo non vuol dire che non dovresti scrivere unit test, ma ogni singola funzione pubblica necessita di un unit test? Direi che la risposta è no. Il codice che sta eseguendo la convalida dell'input dell'utente richiede un test unitario? Molto probabilmente in quanto è un punto di errore comune nelle applicazioni.

Questa è una di quelle aree in cui l'esperienza entra in gioco, col tempo riconoscerai le parti dell'applicazione che potrebbero beneficiare del test unitario, ma ci vorrà un po 'prima di raggiungere quel punto.


Questo è un buon punto. Devi sapere come scrivere buoni test che catturino il valore del SUT.
Andy,

3
Questo in sostanza copre il modo in cui mi è stato insegnato a fare unit test: scrivere prima i test per coprire le situazioni più importanti / fragili, quindi aggiungere altri test quando i tuoi presupposti si sono rivelati sbagliati (pensavo che qualcosa non potesse "non fallire", ma è successo) .
Ripristina Monica il

38

I progetti realizzati per le classi universitarie differiscono notevolmente dalle applicazioni aziendali che scriverai sul tuo lavoro. La differenza è durata. Per quanto tempo "vive" il progetto universitario? Nella maggior parte dei casi, inizia quando si scrive la prima riga di codice e termina quando si ottiene il segno. Si potrebbe dire che, in effetti, vive solo per il momento dell'implementazione. "Rilascio" è generalmente uguale alla sua "morte".

Il software realizzato per le aziende supera il punto di rilascio-morte del progetto universitario e continua a vivere fino a quando le aziende ne hanno bisogno. Che è molto lungo . Quando si parla di soldi, nessuno spenderà un centesimo rotto per avere "codice più fresco e ordinato". Se il software scritto in C 25 anni fa funziona ancora ed è abbastanza buono (come compreso dalle esigenze dei suoi proprietari di attività), aspettatevi che venga chiesto di mantenerlo (aggiunta di nuove funzionalità, miglioramento di quelle vecchie - modifica del codice sorgente ).

Arriviamo a un punto molto importante: la regressione . Nel posto in cui lavoro abbiamo due team che mantengono due app; uno, ha scritto circa 5-6 anni fa con pochissima copertura di test del codice *, e la seconda, nuova versione della prima applicazione con vera suite di test (unità, l'integrazione e la cosa non altro). Entrambi i team hanno tester manuali (umani) dedicati. Vuoi sapere quanto tempo ci vuole per introdurre una nuova funzionalità abbastanza semplice per la prima squadra? 3-4 settimane. La metà di questo tempo "verifica se tutto il resto funziona ancora". È tempo occupato per i tester manuali. I telefoni squillano, le persone si arrabbiano, qualcosa si rompe di nuovo. La seconda squadra di solito si occupa di tali problemi in meno di 3 giorni.

Non dico affatto che i test unitari rendano il tuo errore di codice soggetto a errori, corretto o con altre parole fantasiose che puoi trovare. Né fanno scomparire magicamente i bug. Ma se combinati con altri metodi di test software automatizzati, rendono le applicazioni molto più gestibili di quanto non sarebbero state altrimenti. Questa è una grande vittoria.

E, ultimo ma non meno importante, il commento di Brian che penso risolve l'intero problema:

(...) aumentano la tua fiducia (o dovrebbero ...) che il codice fa quello per cui l'hai progettato, e continua a fare domani quello che fa oggi.

Perché tra oggi e domani qualcuno potrebbe fare un piccolo cambiamento che causerà l' arresto anomalo del codice del generatore di report così importante . I test spingono le probabilità che lo scoprirai prima che il cliente faccia un po 'dalla tua parte.

* Introducono lentamente sempre più test alla loro base di codice, ma sappiamo tutti come appaiono queste cose.


10
+1000 per il collegamento a Software_Regression. I college espongono i test unitari come qualcosa che devi fare per pura fede, senza spiegare in dettaglio che esiste una malattia da prevenire e controllare e che quella malattia si chiama regressione . (poi c'è il problema con i test di regressione che sono qualcosa di molto diverso dai test unitari, poiché l'unica lettura che ho trovato per spiegarlo bene è il campione gratuito di questo libro )
ZJR

25

la scrittura di unit test per i moduli web ASP.NET è qualcosa che viene fatto spesso, e se lo è: come posso risolvere il problema "ambiente dinamico"?

Non è spesso fatto. Lavorare con gli elementi dell'interfaccia utente non è ciò in cui i test unitari sono efficaci, poiché non esiste un modo eccezionale per verificare a livello di programmazione che le cose giuste finiscano sullo schermo nei posti giusti.

Ragazzi, mi consigliereste di iniziare a scrivere unit test? Penso che potrebbe aiutarmi nella realizzazione effettiva, ma poi di nuovo mi sento come se potesse rallentarmi.

Dove applicabile, sì. Possono essere molto utili per verificare casi specifici in modo ripetibile. Aiutano a fungere da "attrito" contro i cambiamenti fastidiosi e come sicurezza quando si apportano cambiamenti migliori.

Una cosa da notare è che di solito ti rallenteranno.

Questo va bene.

Trascorrere un po 'di tempo ora (se fatto bene) ti farà risparmiare tempo in futuro perché catturano alcuni bug, impediscono il ripetersi di alcuni bug e ti permettono di sentirti più a tuo agio nel fare altri miglioramenti nel codice per evitare che marcisca.


8
+1 per aver effettivamente risposto al caso d'uso della domanda! Tutti gli altri sono saltati sulla parte "unit test" e si sono dimenticati della parte "ASP.NET web form" ...
Izkata,

1
Questa è un'ottima risposta e merita più voti, il motivo è perché hai affrontato le domande e sei stato onesto nella tua valutazione di rallentare lo sviluppatore e non promettere che ogni bug verrà catturato o prevenuto, che è completamente e assolutamente vero.
Mantorok,

11

Mi sono appena laureato in CS e attualmente ho un lavoro come sviluppatore .NET junior (in C # e di solito ASP.NET, moduli web - non ASP.NET MVC). Quando ero ancora all'università, l'argomento del test unitario veniva trattato, ma non ne ho mai visto i benefici.

Questo perché non hai mai programmato in grande.

Capisco cosa dovrebbe fare: determinare se un blocco di codice o meno è adatto all'uso, ma in realtà non ho mai dovuto scrivere un test unitario prima. (né ho mai sentito il bisogno di ..)

La scrittura di unit test obbliga il codice a conformarsi a una determinata struttura mentale che è testabile, ben documentata e affidabile. È molto più di quello che affermi.

-Ho letto che spesso i test unitari si svolgono scrivendo "mock". Anche se capisco questo concetto, non riesco a capire come dovrei scrivere simulazioni per siti Web completamente dinamici e dove quasi tutto dipende dai dati che provengono da un database.

deride l'accesso al database con una classe simulata che restituisce classi modello piene di dati ben definiti e codificati. oppure riempire un database di test con i dati del dispositivo e lavorare da lì.

Ragazzi, mi consigliereste di iniziare a scrivere unit test?

diavolo sì. Leggi prima "Test Driven Development" di Beck .

Penso che potrebbe aiutarmi nella realizzazione effettiva, ma poi di nuovo mi sento come se potesse rallentarmi.

Ti rallenta ora. Ma quando devi eseguire il debug per ore anziché giorni, cambierai idea.

qualsiasi consiglio sarà apprezzato :)

Test. Fidati di me. Purtroppo deve anche essere una politica di gestione, ma è qualcosa che consente di risparmiare tempo. I test rimangono, sono lì, ora e in futuro. Quando cambi la piattaforma ed esegui i test e funzionano ancora, sai che le tue cose funzionano come previsto.


8

Modifica: ovviamente mi sono unito al dogpile TDD pro / con e ho saltato la domanda n. 1:

1 - Implementazione di unit test nei moduli web ASP.net:

Prima di tutto, se pensi di riuscire a farli andare con MVC, combatti per questo come un rabbioso orso delle caverne. Come sviluppatore front-end / UI, .net MVC è ciò che mi ha aiutato a smettere di odiare .net in modo da potermi concentrare meglio sull'odiare ogni soluzione web Java in cui mi sia mai imbattuto. I test unitari sono problematici perché i moduli web offuscano davvero le linee tra il server e il lato client. In qualsiasi tentativo di eseguire test unitari, mi concentro sulla manipolazione dei dati e (si spera) presumo che i moduli web gestiscano la normalizzazione dell'input dell'utente per te.

2 - In primo luogo se i test unitari valgono la pena:

Va bene, divulgazione completa:

  • Sono per lo più autodidatta. La mia formazione formale si riduce a come un JavaScript, un PHP e una classe C # e il mio studio personale sui principi OOP e la lettura di cose come Design Patterns.

Però,

  • Per lo più scrivo per il web lato client e la parte di programmazione effettiva è in uno dei linguaggi più veloci e sciolti là fuori per quanto riguarda la tipizzazione dinamica, le funzioni di prima classe e la mutabilità degli oggetti.

Ciò significa che non scrivo per lo stesso compilatore o macchina virtuale. Scrivo per 4-20 diverse interpretazioni di tre lingue (sì, due di esse sono puramente dichiarative ma determinano anche lo spazio fisico fondamentale dell'interfaccia utente con cui sto lavorando in diversi modi a volte) e lo faccio da quando le interpretazioni erano un molto più vario di quello che sono oggi. E no, non sono solo un bambino che collega le cose JQuery per le app usa e getta. Contribuisco a costruire e mantenere elementi abbastanza sofisticati con molta complessità degli elementi dell'interfaccia utente.

Quindi sì, ci sono molte opportunità per qualche modifica qua e là per creare una grande cascata di fallimenti se le tue capacità di progettazione sono cazzate complete o stai lanciando sviluppatori mediocri in grandi quantità con 1-2 problemi di sviluppo di qualità.

La mia comprensione di ciò che TDD dovrebbe fare per te è che i test mirano davvero a costringerti a prendere in considerazione la progettazione più attentamente e a concentrarti sui requisiti. Abbastanza giusto, ma il problema qui è che sovverte ciò che dovresti fare, che sta progettando in un'interfaccia, in qualcosa di sottilmente ma fondamentalmente diverso, che sta progettando per i test di un'interfaccia. La differenza per me è tra disegnare un'immagine chiara di cui la mamma non dovrà indovinare il significato e riempire l'intera pagina con il verde molto velocemente in modo da poter essere il primo bambino a schiaffeggiare i suoi pastelli sul tavolo e gridare "fatto! " Spostando la priorità sui risultati rispetto al processo e alla progettazione, in pratica stai incoraggiando l'implementazione continua del codice Garbage, che è in genere ciò che è stato alla radice dei tuoi problemi in primo luogo.

E poi ovviamente c'è il "non-vero-punto-di" ma spesso elogiato vantaggio collaterale dei test unitari che ti aiutano a rilevare errori di regressione. I sostenitori del TDD tendono ad essere un po 'sospettosi sul fatto che questo sia effettivamente l'obiettivo o solo un effetto collaterale elegante, IMO, perché sanno dannatamente bene o sospettano almeno che questo non sia semplicemente sufficiente per stabilire l'assenza di bug nel tuo codice, specialmente in un linguaggio più dinamico come JavaScript, dove supporre che tu possa persino prevedere ogni possibile scenario in una lunga catena di dipendenze è insensato.

C'è un posto per i test automatizzati in JS, ma un uso molto migliore del tuo tempo che collegare un test unitario a ogni singola "unità" del tuo codice che viene a contatto con un altro sta assicurando che tu non abbia un sacco di immondizia oggetti che duplicano il lavoro o il cui uso previsto è semanticamente ambiguo lì in primo luogo. Segui il principio DRY. Estrarre le cose per riutilizzo / portabilità quando il valore di farlo diventa evidente (e non un minuto prima). Stabilisci processi e modi coerenti di fare le cose seguendo più un principio di carota che di bastone (cioè è troppo facile usare le tue cose nel modo giusto per preoccuparti di voler farlo nel modo sbagliato). E per amore di tutte le cose foo and bar, non indulgere mai in massicci schemi anti ereditari a cascata come mezzo per riutilizzare il codice.

Tutto quanto sopra mi ha aiutato a ridurre i bug difficili da diagnosticare nel mio codice in modo serio e puoi fidarti che è una grande priorità per qualcuno che è arrivato come sviluppatore con un set di browser che non aveva niente di meglio da dirti di " uh c'è stato un problema con un oggetto di tipo "Oggetto" in questo numero di riga immaginario in un file non specificato. " (Accidenti, grazie a IE6) TDD, nella mia linea di lavoro, non incoraggerebbe queste cose. Sposterebbe l'attenzione sui risultati del 100% rispetto al processo in cui ciò che è compreso tra i punti A e B non ha importanza finché funziona. È una perdita di tempo che sarebbe meglio applicare per assicurarsi che le tue cose siano leggibili, portatili e facili da modificare senza molta confusione in primo luogo.

O forse sto solo diventando eccessivamente sprezzante sul paradigma in cui sono radicato, ma secondo me, farlo bene in primo luogo è un uso molto più efficace del tempo rispetto a coprire il culo per quando tu o tutti gli altri sul vostro la squadra fa male. E nulla dovrebbe costringerti a considerare la progettazione piuttosto che implementare le cose. Il design dovrebbe essere l'altare di ogni programmatore. E tutto ciò che "ti costringe" a fare la cosa giusta o ti protegge da te stesso dovrebbe essere visto con lo stesso sospetto riservato alle bottiglie di olio di serpente, IMO. L'olio di serpente nell'IT moderno e lo sviluppo generale, se non si è ancora a conoscenza, viene venduto dalla tonnellata liquida.


1
Scrivo molti test unitari. Non scriverò codice senza di loro. Ma sono d'accordo con i tuoi sentimenti. I test dovrebbero guidare , non guidare lo sviluppo. Non puoi automatizzare il pensiero attento a un problema.
FizzyTea,

Non ho problemi con i test automatizzati. Ma le adozioni all'ingrosso di esso in ogni congiuntura mi sembrano più panico che processo. Risparmiare tempo per la progettazione e automatizzare i test e la convalida nei punti in cui è probabile che interagisca con una varietà di cose che non controlli è il modo in cui preferisco.
Erik Reppen,

5

Nella mia esperienza, i test unitari sono davvero molto utili, quando inizi con loro e rimani con loro, cioè Test-Driven Development. Ecco perché:

  • I test unitari ti costringono a pensare a ciò che vuoi e a come verificare che tu l'abbia ottenuto, prima di scrivere il codice che lo fa . In uno scenario TDD, scrivi prima il test. Devi quindi sapere che cosa deve fare il codice che stai per scrivere e come puoi verificarlo, al fine di scrivere un test "rosso" da rendere "verde" scrivendo il codice in passalo. In molti casi questo ti costringe a pensare solo un po 'di più all'algoritmo che stai per scrivere per superare questo test, il che è sempre una buona cosa in quanto riduce gli errori logici e i "casi angolari". Mentre si sta scrivendo il test, si sta pensando "come potrebbe questo fallire" e "che cosa sono io non testando qui", che porta ad un algoritmo più robusto.

  • I test unitari ti costringono a pensare a come verrà consumato il codice che stai per scrivere . Prima di apprendere TDD, ci sono state MOLTE volte in cui ho scritto codice aspettandomi che una dipendenza funzionasse in un modo, e poi mi è stata data una dipendenza scritta da un collega che ha funzionato in un modo completamente diverso. Mentre questo è ancora possibile con TDD, il test unitario che stai scrivendo ti costringe a pensare a come vuoi usare l'oggetto che stai scrivendo, perché è un esempio di utilizzo di detto oggetto. Si spera quindi di scrivere l'oggetto in modo che sia facile da consumare e quindi adattarsi se necessario (anche se la programmazione su interfacce predefinite è una soluzione globale migliore a questo problema che non richiede TDD).

  • I test unitari ti consentono di "codificare testando" . Uno strumento di refactoring come ReSharper può essere il tuo migliore amico se lo lasci fare. È possibile utilizzarlo per definire lo scheletro di nuove funzionalità mentre si sta definendo l'utilizzo in un test.

    Ad esempio, supponiamo che sia necessario creare un nuovo oggetto MyClass. Si inizia creando un'istanza di MyClass. "Ma MyClass non esiste!", Si lamenta ReSharper. "Quindi crealo" dici, con una pressione di Alt + Invio. E presto hai la tua definizione di classe. Nella riga successiva del codice di test si chiama un metodo MyMethod. "Ma questo non esiste!", Afferma ReSharper. "Quindi crealo", ripeti, con un altro Alt + Invio. Con poche pressioni di tasti hai definito lo "scheletro" del tuo nuovo codice. Mentre continui a perfezionare l'uso, l'IDE ti dirà quando qualcosa non va bene e di solito la soluzione è abbastanza semplice che l'IDE o uno strumento che si collega al suo interno sa come risolverlo.

    Esempi più estremi si conformano al modello "Triple-A"; "Organizza, agisci, asserisci". Imposta tutto, esegui la logica effettiva che stai testando, quindi asserisci che la logica è corretta. Codificando in questo modo, è molto naturale codificare la soluzione nel test; quindi, con alcuni tasti premuti, è possibile estrarre quella logica e metterla da qualche parte dove può essere utilizzata nel codice di produzione, quindi apportare piccole modifiche al test che la puntano nella nuova posizione della logica. Farlo in questo modo ti costringe a progettare il codice in modo modulare e facile da riutilizzare perché le unità che stai testando devono essere ancora accessibili.

  • I test unitari eseguono molti ordini di grandezza più velocemente di qualsiasi test manuale a cui potresti pensare. C'è un punto, incontrato molto rapidamente nel caso di progetti più grandi, in cui il tempo di test unitario inizia a ripagarsi da solo riducendo il tempo impiegato per i test manuali. Devi SEMPRE eseguire il codice che hai appena scritto. Tradizionalmente, lo hai fatto manualmente, avviando un programma di grandi dimensioni, navigando attraverso l'interfaccia utente per impostare la situazione per cui hai modificato il comportamento e quindi verificando nuovamente i risultati attraverso l'interfaccia utente o sotto forma di dati prodotti. Se il codice era TDDed, è sufficiente eseguire i test unitari. Ti garantisco che se stai scrivendo buoni test unitari, quest'ultima opzione sarà molte volte più veloce della prima.

  • I test unitari registrano la regressione . Ancora una volta, ci sono state molte volte prima che venissi a conoscenza del TDD in cui ero entrato, fatto ciò che pensavo fosse una modifica chirurgica a un pezzo di codice, verificato che il cambiamento correggesse un comportamento errato (o producesse un nuovo comportamento desiderato) nella situazione segnalata e lo ha verificato per il rilascio, solo per scoprire che la modifica ha rotto qualche altro caso angolare in un modulo completamente diverso che è successo per riutilizzare lo stesso blocco di codice. In un progetto TDDed, posso scrivere un test per verificare una modifica che sto per fare, apportare la modifica, quindi eseguire la suite completa e se tutti gli altri usi del codice sono stati TDDed e la mia modifica ha rotto qualcosa, i test per quelli altre cose falliranno e posso indagare.

    Se gli sviluppatori dovessero trovare e testare manualmente tutte le righe di codice che potrebbero essere interessate da una potenziale modifica, nulla verrebbe mai fatto perché il costo di determinare l'impatto di una modifica renderebbe impossibile la modifica. Per lo meno, nulla sarebbe SOLIDO e quindi facilmente mantenibile, perché non oseresti mai toccare qualcosa che potrebbe essere usato in più luoghi; dovresti invece creare la tua soluzione molto simile ma incorporando la modifica minore per questo caso, violando SRP e probabilmente OCP e trasformando lentamente la tua base di codice in una trapunta di patchwork.

  • I test unitari modellano l'architettura in modo tipicamente vantaggioso . I test unitari sono test eseguiti separatamente da qualsiasi altra logica. Per poter testare l'unità del codice, quindi, è necessario scrivere il codice in modo che sia possibileisolalo. Buone decisioni di progettazione come l'accoppiamento lento e l'iniezione di dipendenza si scuotono così naturalmente dal processo TDD; le dipendenze devono essere iniettate in modo che in un test sia possibile iniettare un "mock" o "stub" che produce l'input o gestisce l'output per la situazione testata senza creare "effetti collaterali". La mentalità del "primo utilizzo" di TDD generalmente porta alla "codifica delle interfacce", l'essenza dell'accoppiamento libero. Questi buoni principi di progettazione consentono quindi di apportare modifiche alla produzione, come la sostituzione di un'intera classe, senza richiedere che grandi quantità della base di codice vengano modificate per adattarsi.

  • Prove di unità mostrano che il codice funziona, invece di provare le opere di codice . A prima vista potresti pensare che sia uno svantaggio; sicuramente la prova è meglio della dimostrazione? La teoria è fantastica; la teoria computazionale e algoritmica è il fondamento del nostro lavoro. Ma una prova matematica della correttezza di un algoritmo non è una prova della correttezza dell'implementazione . Una prova matematica mostra solo che il codice che aderisce all'algoritmo dovrebbe essere corretto. Un test unitario mostra che il codice effettivamente scritto fa quello che pensavi avrebbe fatto, ed è quindi la prova che è corretto. Questo è generalmente molto più utile di una dimostrazione teorica.

Ora, detto tutto ciò, ci sono degli svantaggi nel test unitario:

  • Non puoi testare tutto tutto. È possibile progettare il sistema in modo da ridurre al minimo il numero di LOC non coperti da un test unitario, ma ci saranno semplicemente alcune aree del sistema che non possono essere testate dall'unità. Il tuo livello di accesso ai dati può essere deriso quando utilizzato da altri codici, ma il livello di accesso ai dati stesso contiene molti effetti collaterali e in genere non è possibile testare l'unità (la maggior parte?) Di un repository o DAO. Allo stesso modo, il codice che utilizza file, imposta connessioni di rete, ecc. Ha effetti collaterali integrati e semplicemente non è possibile testare l'unità della riga di codice che lo fa. Gli elementi dell'interfaccia utente spesso non possono essere testati in unità; puoi testare il codice dietro metodi come i gestori di eventi, puoi costruire unità di test costruttori e verificare che i gestori siano collegati, ma semplicemente non esiste un sostituto nel codice per un utente che fa clic con il mouse su un particolare elemento grafico e guarda il gestore essere chiamato. Raggiungere questi confini tra ciò che può e non può essere adeguatamente testato dall'unità è chiamato "raschiare il bordo del sandbox"; oltre quel punto sei limitato all'utilizzo di test di integrazione, test di accettazione automatizzati e test manuali per verificare il comportamento.

  • Molti vantaggi del test unitario non si applicano senza TDD. È perfettamente possibile scrivere codice, quindi scrivere test che esercitano il codice. Sono ancora "unit test", tuttavia scrivendo prima il codice, perdi molti dei vantaggi inerenti allo sviluppo "test-first": il codice non è necessariamente progettato in un modo che può essere facilmente testato o addirittura utilizzato in produzione ; non ottieni il processo di "doppio controllo" inerente alla scrittura del test e al pensiero di ciò a cui non avevi pensato; non si codifica testando; e se scrivi il codice, testalo manualmente e vedi che funziona, allora codifica un test unit che fallisce, che è sbagliato, il codice o il test? I tuoi principali vantaggi sono la prevenzione della regressione (verrai avvisato quando il codice che in precedenza ha superato i test ora fallisce) e la verifica ad alta velocità rispetto ai test manuali. La perdita di TDD '

  • Il test unitario introduce un sovraccarico . Molto semplicemente, stai scrivendo il codice per testare il codice che stai scrivendo. Ciò aumenterà necessariamente il LOC totale di un progetto di sviluppo e, sì, il LOC per i test può superare il LOC per il progetto effettivo. Sviluppatori ingenui e non sviluppatori esamineranno questo stato di cose e affermeranno che i test sono una perdita di tempo.

  • Il test unitario richiede disciplina. Devi scrivere test che esercitino adeguatamente la base di codice (buona copertura del codice), devi eseguirli regolarmente (come ogni volta che commetti una modifica, l'intera suite dovrebbe essere eseguita) e devi mantenere tutto "verde" ( superamento di tutti i test). Quando le cose si rompono, è necessario risolverle riparando il codice che non soddisfa le aspettative o aggiornando le aspettative dei test. Se cambi i test, dovresti chiedere "perché", e tenere d'occhio molto attentamente te stesso; è incredibilmente allettante cambiare semplicemente le asserzioni fallimentari per adattarle al comportamento attuale, o semplicemente rimuovere i test falliti; ma, quei test dovrebbero essere basati sui requisiti e quando i due non corrispondono hai un problema. Se queste cose non vengono fatte,

  • Il collaudo dell'unità richiede più attrezzature. La solita soluzione al bisogno di disciplina di cui sopra, e una naturale tendenza degli umani a diventare pigri e compiacenti, è un "build-bot" che esegue un pacchetto software "Integrazione continua" come TeamCity, CruiseControl, ecc., Che esegue test unitari, calcola metriche di copertura del codice e ha altri controlli come "triple-C" (conformità della convenzione di codifica, alla FxCop). L'hardware per il bot di compilazione deve essere ragionevolmente performante (altrimenti non terrà il passo con la percentuale di check-in di codice che il team medio effettuerà) e le procedure di check-in sul bot devono essere aggiornate (se viene creata una nuova libreria di unit test, gli script di build che eseguono unit test devono essere modificati per cercare in quella libreria). Questo è meno lavoro di quanto sembri, ma in genere richiede un po 'di esperienza tecnica da parte di almeno alcune persone nel team che sanno come funzionano i grintosi dei vari processi di compilazione (e quindi possono automatizzarli negli script e mantenerli). Inoltre richiede ancora disciplina sotto forma di attenzione quando la build "si rompe" e risolve qualsiasi cosa abbia causato la rottura (corretta) della build prima di effettuare il check in di qualsiasi cosa nuova.

  • I test unitari possono forzare l'architettura del codice in modo non ideale . Sebbene TDD sia in genere buono per la modularità e la riusabilità del codice, può essere dannoso per la corretta accessibilità del codice. Gli oggetti e i membri, collocati nelle librerie di produzione, non possono essere privati ​​o interni se vengono utilizzati direttamente dai test unitari. Ciò può causare problemi quando altri programmatori, ora vedendo un oggetto, cercano di usarlo quando dovrebbero invece usare qualcos'altro presente nella libreria. Le revisioni del codice possono essere d'aiuto in questo, ma possono essere fonte di preoccupazione.

  • I test unitari generalmente vietano gli stili di codifica "sviluppo rapido di applicazioni". Se stai scrivendo unit test, non stai programmando "veloce e sciolto". In genere è una buona cosa, ma quando sei sotto una scadenza imposta al di fuori del tuo controllo, o stai implementando un cambiamento di portata molto piccola e lo stakeholder (o il tuo capo) si sta chiedendo perché tutto questo innesto deve avvenire solo per cambiare una riga di codice, può semplicemente essere impossibile scrivere e mantenere la suite di test unitaria corretta. I processi agili in genere aiutano in questo, consentendo agli sviluppatori di dire qualcosa in termini di requisiti di tempo; ricordate, tutto ciò che il venditore deve fare è dire "sì, possiamo" e ottengono il controllo delle commissioni, a meno che il processo non coinvolga le persone che devono effettivamente svolgere il lavoro dicendo "no, non possiamo" ed essere prestate attenzione. Ma non tutti sono Agili e Agile ha i suoi limiti.


4

I test unitari sono utili se utilizzati correttamente; ci sono vari problemi con la tua logica.

"Quando sto sviluppando, sottopongo a molte prove ed errori", ha detto Kevin.

Guarda la programmazione per coincidenza. È meglio capire cosa dovrebbe fare un codice e quindi dimostrare che lo fa tramite un unit test. Non dare per scontato che un codice funzioni semplicemente perché l'interfaccia utente non si è interrotta durante l'esecuzione del programma!

s writing unit tests for ASP.NET web forms something that is done often

Non ho conoscenza dei dati statistici per dire con quale frequenza le persone testano i moduli web. Non importa. L'interfaccia utente è difficile da testare e anche i test unitari non devono essere accoppiati a un'interfaccia utente. Separa la tua logica in livelli, librerie di classi che possono essere testate. Testare l'interfaccia utente separatamente dalla logica di back-end.

So, question number 2: Would you guys advise me to start writing unit tests?

Sì. Una volta che ti ci abitui, ti accelerano. La manutenzione richiede molto più tempo e denaro della fase di sviluppo iniziale. La manutenzione è notevolmente supportata dai test unitari, anche con i test iniziali e la riparazione dei bug.


Esistono framework di test che possono eseguire test su pagine aspx per testare semplicemente se le pagine vengono caricate correttamente o meno in diversi scenari. Questo potrebbe non essere abbastanza buono, ma è meglio di niente.
timore

4

A livello pratico, i test unitari possono essere estremamente utili per un motivo molto importante: è possibile testare un bit di un codice alla volta.

Quando si scrive un'intera sequenza di passaggi complessi e li si esegue il debug alla fine, si tende a trovare molti bug e il processo è generalmente più difficile perché si è più avanti nel processo. In Visual Studio è possibile generare un test rapido, modificarlo un po 'ed eseguire SOLO quel test . Quindi si sa che ad esempio un metodo che chiama quel metodo può fare affidamento su di esso. Quindi aumenta la fiducia.

I test unitari non dimostrano che il tuo programma sia corretto! : I test unitari verificano le regressioni nel codice sensibile e consentono di testare nuovi metodi scritti.

I test unitari non hanno lo scopo di testare i front-end : pensa a un test unitario come a quel piccolo progetto che crei per testare un nuovo metodo che stai scrivendo o qualcosa del genere, non come una sorta di condizione che il tuo codice deve soddisfare.

Il test unitario funziona alla grande per ambienti collaborativi : se devo fornire un metodo a un collega che utilizza una mia tecnologia completamente diversa, come ad esempio lo chiama da iOS, allora posso scrivere rapidamente un test unitario per vedere se il metodo che desidera a) Riprende i dati corretti b) Esegue secondo le sue specifiche c) Non ha colli di bottiglia.


"I test unitari non hanno lo scopo di testare i front-end" Chi lo dice? Non lo sto mettendo in discussione. Vorrei solo sapere perché molte persone sembrano avere un'idea sbagliata e mi piacerebbe sbatterle con il bastone che dice-non-cosa-questo-enorme-influente-avvocato-TDD-fonte.
Erik Reppen,

Alcune persone, me compreso, hanno avuto questo malinteso quando hanno incontrato per la prima volta i test unitari, quindi lo sto chiarendo. Non so perché ti senti come se ti sfidassi, in effetti sono pienamente d'accordo con te.
Tjaart,

4

Una cosa che non sembra essere toccata è la complessità di testare diversi tipi di codice.

Quando hai a che fare con cose con input e output semplici è generalmente facile testare le unità e se i test sono scelti tenendo conto dei casi limite del codice testato, ti daranno molta fiducia che hanno ragione. Non scrivere test per tale codice sarebbe folle. (Si noti che la maggior parte del codice che va nelle librerie soddisfa questi criteri.)

Tuttavia, in altri casi si finisce per costruire enormi simulazioni da testare perché il codice sta giocando con dati sottostanti complessi (di solito un database ma non deve essere) o produce dati di output molto complessi (si pensi a una routine che gira un valore iniziale in un livello di gioco per un esempio piuttosto estremo) e il test unitario non è poi così utile. Coprire tutto nei casi di test di solito è un sogno irrealizzabile e quando trovi un bug è quasi sempre un caso a cui non hai mai pensato e che quindi non potresti aver costruito un test.

Non ci sono proiettili d'argento, qualcosa raffigurato come un proiettile d'argento non è altrettanto buono come sostengono i suoi sostenitori, ma ciò non significa che sia inutile.


4

Scrivere unit test per l'applicazione di moduli Web ASP.NET NON è comune e molto difficile da realizzare. Tuttavia, ciò non significa che il progetto debba saltarlo.

I test unitari sono corner stonesapplicazioni mission-critical e forniscono affidabilità e tranquillità che le funzionalità principali svolgono come previsto.

In realtà è possibile introdurre test di unità molto più facilmente con un modello ASP.NET MVP che potrebbe essere utilizzato nello sviluppo dei moduli Web. Introdurrà la separazione delle preoccupazioni e ability to write essential unit tests.

Alcuni riferimenti che potrebbero essere utili da guardare sono:


2
+1 Non importa se stai eseguendo o meno test unitari, MVP è la strada da percorrere quando lavori con Web Forms (forse anche WinForms).
simoraman

3

Lo scopo dei test unitari è di permetterti di cambiare in sicurezza il tuo codice (refactoring, miglioramento ecc.) Senza il timore di poter rompere qualcosa all'interno del sistema. Ciò si rivela molto utile per le applicazioni di grandi dimensioni, quando non si conoscono realmente tutti gli effetti della modifica del codice (nonostante l'accoppiamento lento).


6
Senza paura è un falso senso di sicurezza.
Coder

Forse "meno paura" è una frase migliore, ma la risposta è ancora ampiamente corretta.
Ripristina Monica il

1
@Coder Se i tuoi test superano il refactoring, allora puoi essere abbastanza sicuro che il miglioramento del codice non ha cambiato il modo in cui si comporta l'applicazione (approssimativamente parlando non hai introdotto nuovi bug, ma questo non è necessariamente vero perché non puoi raggiungere Copertura del test al 100%).
m3th0dman,

2

È la mia esperienza che , i test unitari sono utili.

Il test unitario consiste nel separare parti del codice che scrivi e assicurarti che funzionino separatamente. Questo isolamento potrebbe effettivamente comportare la creazione di oggetti falsi o finti per parlare con l'oggetto che stai testando, oppure potrebbe non esserlo. Dipende molto dall'architettura del tuo oggetto.

Il test unitario offre vari vantaggi:

In primo luogo, ciò garantisce che le unità testate funzionino nel modo in cui tu, lo sviluppatore, pensi che dovrebbero funzionare. Mentre questo è meno di quanto sembri: non dice necessariamente che l'oggetto funzioni correttamente; solo che funziona come pensi che dovrebbe funzionare, è un'affermazione molto più forte del metodo di prova ed errore che è necessario senza test unitari.

Inoltre, garantisce che le unità continuino a funzionare nel modo in cui tu, lo sviluppatore, pensavi che dovessero funzionare. Il software cambia e questo può influire sulle unità in modi inaspettati.

Un altro effetto collaterale è che significa che le unità si prova fanno lavorare in isolamento. Questo in genere significa che inizi a programmare interfacce piuttosto che classi concrete, riducendo l'accoppiamento e aumentando la coesione: tutti i segni distintivi comuni di un buon design. Sì: semplicemente abilitando le unità di codice ad avere unit test migliorerà naturalmente il design del codice.

Però...

Il test unitario non è la fine del test. Altri tipi di test sono ancora richiesti. Ad esempio, anche quando hai dimostrato che le unità funzionano nel modo in cui ti aspetti che funzionino, devi comunque dimostrare che ogni unità funziona nel modo in cui le unità che parlano con essa si aspettano che funzioni. Cioè, i componenti si integrano correttamente tra loro?


1

Per le app semplici con un numero limitato di livelli da testare (Finestra principale -> sottomenu), forse compilare per eseguire per verificare le modifiche è ok.

Per le app più grandi in cui sono necessari 30 anni di navigazione per ottenere la pagina che stai testando, questo risulta essere molto costoso.


1

Voglio aggiungere un nuovo lato (in realtà, piuttosto vecchio) a questo: i test unitari non sono così utili se il tuo codice è ben progettato .

So che la maggior parte dei programmatori non fa più la progettazione del programma, lo faccio ancora, e ho scoperto che i test unitari erano una necessità piuttosto dispendiosa in termini di tempo per adattarsi a una cultura TDD, ma finora ho incontrato solo 1-2 minori bug per migliaia di righe di test del mio codice - non solo quello che ho scritto, ma anche quello che hanno scritto i tester ufficiali.

Suppongo che non farai più nemmeno la progettazione del programma - la gente attuale ti spingerà in uno stampo per non farlo - ma forse vale la pena ricordare che il test unitario è un metodo di efficienza molto basso rispetto al design.

Questo è un argomento dijsktraian: il test unitario può essere eseguito solo su un programma sufficientemente dettagliato per essere eseguito.

Se disegni diagrammi di flusso / stati / azioni, diagrammi di sequenza, inventari di oggetti (e ultimo e minimo, diagrammi di classe) per il tuo codice prima di scriverlo effettivamente, sarai in grado di eliminare la maggior parte dei bug potenzialmente minacciosi semplicemente tracciando le tue linee e il controllo dei tuoi nomi.

Oggi i diagrammi di classe sono generati dal codice, che contiene centinaia, a volte migliaia di classi e sono completamente inutilizzabili: qualsiasi cosa che contenga più di 15 elementi è al di là del riconoscimento umano.

Devi sapere cosa contano le classi 10 + -5 o cosa fai adesso ed essere in grado di controllare il tuo codice da più punti di vista, ogni diagramma che rappresenta ESATTAMENTE i punti di vista che stai osservando e ucciderai migliaia di bug su carta.

  • Verifica in un codice dinamico se i tipi sono soddisfatti (mostrando semplicemente i tipi di input / output su un diagramma di flusso e collegandoli con una matita o un colore diverso),
  • controllando se tutti gli stati sono gestiti (controllando la pienezza delle vostre condizioni),
  • tracciare le linee per assicurarsi che tutto finisca (ogni diagramma di flusso dovrebbe essere un automatismo a stati finiti deterministico completamente definito, per i matematici
  • assicurarsi che determinati componenti non abbiano nulla a che fare l'uno con l'altro (estraendo tutte le loro dipendenze) (buono per la sicurezza)
  • semplificando il codice convertendo le dipendenze in associazioni (le dipendenze provengono da quali classi usano i metodi membro)
  • verifica dei nomi, ricerca di prefissi comuni, cancellazione dei sinonimi, ecc ...

c'è solo molto più facile ...

Inoltre, ho scoperto che le mie applicazioni sono più utilizzabili, se provengono direttamente da casi d'uso ... se i casi d'uso sono scritti bene (soggetto verbo ACTOR, il Maintainer richiede di aprire il bancomat) ... Che

Ho fatto il codice con il 95 +% delle coperture del codice. Certo, a volte faccio test unitari, esp. per i controlli al contorno nei calcoli, ma devo ancora incontrare gravi regressioni (gravi: non viene cancellato in 24 ore) per non aver utilizzato i test unitari anche per i refactoring.

A volte non faccio una sola riga di codice per 3-4 giorni consecutivi, solo disegnando. Quindi, in un giorno, scrivo 1500-2000 righe. Il giorno dopo, sono quasi tutti pronti per la produzione. A volte vengono scritti test unitari (con l'80% di copertura), a volte (in aggiunta) ai tester viene chiesto di provare a romperlo, ogni volta, ad alcune persone viene chiesto di esaminarlo guardandolo.

Devo ancora vedere quei test unitari trovare qualcosa.

Vorrei che il pensiero progettuale venisse al posto di TDD ... ma TDD è molto più semplice, è come andare con una mazza ... progettare ha bisogno di pensare e tu sei sempre alla ricerca della tastiera.


Penso che tu possa progettare alla tastiera. Ma pianificare e organizzare il codice richiede molto più pensiero che semplicemente inciampare nell'input all'output in classi che potrebbero anche essere funzioni monolitiche.
Erik Reppen,

Fidati di me, le funzioni monolitiche non si adattano a un foglio A4 (o US Letter). A volte quando sono pigro faccio "design" sulla tastiera, ma non è della stessa qualità. Ogni volta che faccio uno sviluppo serio, disegno con UML. Quando li disegni, stai cercando di spiegare a te stesso e agli altri in un modo molto limitato ma ancora strutturato cosa sta succedendo e quando sei in grado di spiegare il codice da ogni singola prospettiva, quindi, solo allora digiti e all'improvviso tutti i tuoi bug sono quasi tutti errori di battitura ...
Aadaam,
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.