Quando il test dell'unità è inappropriato o non necessario? [duplicare]

98

Sembra essere generalmente assunto (almeno per Overflow dello stack) che dovrebbero esserci sempre dei test unitari e che dovrebbero essere tenuti aggiornati. Ma sospetto che i programmatori facciano in modo che queste asserzioni funzionino su diversi tipi di progetti da parte mia - lavorano su software di alta qualità, di lunga durata e spedito, in cui i bug sono davvero una brutta cosa.

Se questa è la fine dello spettro in cui il test unitario è più prezioso, qual è l'altra estremità? Dove sono i test unitari meno preziosi? In quali situazioni non ti daresti fastidio? Dove sarebbe lo sforzo di mantenere i test non vale il costo?

    
posta Steve Bennett 05.05.2012 - 14:14
fonte

16 risposte

97

Personalmente non scriverò test unitari per situazioni in cui:

  1. Il codice non ha rami è banale. Un getter che restituisce 0 non ha bisogno di essere testato, e le modifiche saranno coperte dai test per i suoi consumatori.

  2. Il codice passa semplicemente attraverso un'API stabile. Suppongo che la libreria standard funzioni correttamente.

  3. Il codice deve interagire con altri sistemi distribuiti; allora è richiesto un test di integrazione.

  4. Se il test di successo / fallimento è qualcosa che è così difficile da quantificare da non essere attendibilmente misurabile, come la steganografia che è impercettibile per gli esseri umani.

  5. Se il test stesso è un ordine di grandezza più difficile da scrivere rispetto al codice.

  6. Se il codice è di tipo throw-away o segnaposto. Se c'è qualche dubbio, prova.

risposta data 28.09.2014 - 20:06
fonte
67

A meno che tu non abbia intenzione di scrivere il codice senza testarlo, dovrai sempre sostenere il costo del test.

La differenza tra avere test unitari e non averli è la differenza tra il costo di scrittura del test e il costo di eseguirlo rispetto al costo del test a mano.

Se il costo di scrittura di un test unitario è di 2 minuti e il costo dell'esecuzione del test dell'unità è praticamente pari a 0, il costo del test manuale del codice è di 1 minuto, quindi si interrompe anche quando si esegue il test due volte.

Per molti anni ho capito male che non avevo abbastanza tempo per scrivere test unitari per il mio codice. Quando ho fatto dei test, erano cose gonfie e pesanti che mi hanno solo incoraggiato a pensare che avrei dovuto scrivere solo unit test quando sapevo che erano necessari.

Recentemente sono stato incoraggiato a utilizzare Test Driven Development e ho scoperto che si trattava di una rivelazione completa. Ora sono fermamente convinto di non avere il tempo non per scrivere test unitari.

Nella mia esperienza, sviluppando con i test in mente si finiscono con interfacce più pulite, classi più focalizzate e amp; moduli e generalmente più SOLID , codice verificabile.

Ogni volta che lavoro con un codice legacy che non ha test unitari e devo testare manualmente qualcosa, continuo a pensare "questo sarebbe molto più veloce se questo codice avesse già dei test unitari". Ogni volta che devo provare ad aggiungere funzionalità di unit test al codice con un accoppiamento elevato, continuo a pensare che "sarebbe molto più semplice se fosse stato scritto in modo disaccoppiato".

Confronto e contrasto tra le due stazioni sperimentali che supporto. Uno è stato in giro per un po 'e ha una grande quantità di codice legacy, mentre l'altro è relativamente nuovo.

Quando si aggiungono funzionalità al vecchio laboratorio, spesso si arriva al laboratorio e si impiegano molte ore a lavorare sulle implicazioni della funzionalità di cui hanno bisogno e su come posso aggiungere quella funzionalità senza influire su nessuna delle altre funzionalità. Il codice semplicemente non è impostato per consentire il test off-line, quindi praticamente tutto deve essere sviluppato on-line. Se provassi a sviluppare offline, avrei finito con più oggetti fittizi di quanto sarebbe ragionevole.

Nel laboratorio più recente, di solito posso aggiungere funzionalità sviluppandolo off-line sulla mia scrivania, prendendo in giro solo le cose che sono immediatamente necessarie, e quindi impiegando solo un breve periodo di tempo in laboratorio, stirare eventuali problemi rimanenti, non raccolto fuori linea.

TL; DR versione:

Scrivi un test quando il costo di scrittura del test, più il costo di eseguirlo tutte le volte che è necessario, è probabilmente inferiore al costo di testarlo manualmente tutte le volte che è necessario.

Ricorda però che se usi TDD, è probabile che il costo della scrittura dei test diminuisca man mano che migliora e, a meno che il codice non sia assolutamente banale, probabilmente finirai per eseguire i test più spesso del previsto.

    
risposta data 08.05.2012 - 12:05
fonte
19

Personalmente, in genere non scrivo test unitari per:

  • Modifiche al codice esistente (non legacy) già esistente () Sebbene teoricamente non sia mai troppo tardi per iniziare il test unitario, in pratica i guadagni dall'aggiunta di test unitari al codice che non è mai stato TDDed sono piccoli. L'unico vantaggio è la prevenzione della regressione; puoi vedere l'effetto che una modifica apporta sulle aree che potresti non avere previsto che possa influenzare. Tuttavia, il test unitario dimostra solo che il codice funziona ancora come quando scrissi il test; poiché il test non è stato scritto in base ai requisiti originali, il test non dimostra che l'implementazione corrente sia "corretta". Rendere le modifiche testate in base a tale base di codice è ancora più un incubo nella mia esperienza, quindi semplicemente apportando il cambiamento e esercitando manualmente le aree interessate del programma; devi prima scrivere un test di unità adeguato per il codice in questione (che potrebbe richiedere il refactoring del codice per consentire il mocking e altre architetture TDD-friendly), provare che passa E che il refactoring non ha infranto nulla (e quando questo è il primo test di unità mai scritto per un codice di codice di milioni di LoC, che può essere difficile), quindi cambiare il test per aspettarsi qualcosa di diverso e cambiare il codice per fare passare il test modificato.

  • Layout dell'interfaccia utente e comportamento di livello superiore . In alcuni casi non è fattibile; molti IDE con "designer" dichiarano gli elementi dell'interfaccia utente come privati e non dovrebbero essere concettualmente pubblici. Rendendoli interni richiederebbe il mettere i test unitari negli stessi assembly del codice di produzione (cattivo) e renderli protetti richiederebbe un "proxy di test" che esponga ciò che dobbiamo sapere sui controlli (anche in genere non nel modo in cui è fatto). Anche se fosse accettabile rendere pubblici tutti i controlli e quindi avere accesso al loro tipo, posizione, proprietà di formattazione, ecc., I test che verificano l'UI sono progettati nel modo in cui ci si aspetta che siano estremamente fragili. Di solito puoi ancora eseguire il test dei gestori di unità in codebehinds / viewmodels e quindi è banale dimostrare che facendo clic sul pulsante si attiva il gestore.

  • Persistenza del database . Questo è, per definizione, un test di integrazione. Si prende in giro sempre il repository quando si ha a che fare con il codice che trasferisce i dati al repository e si prendono in giro i ganci di ORM durante lo sviluppo all'interno del repository stesso. Mentre ci sono "test delle unità di database" e puoi "prendere in giro" un database usando qualcosa come SQLite, trovo che questi test non si adattino mai a livello di unità.

  • Codice di terze parti . Esegui il test del tuo codice come preferisci e credi che gli sviluppatori degli strumenti di terze parti che stai utilizzando (inclusi i componenti dello stesso .NET Framework come WPF, WCF, EF, ecc.) Abbiano fatto il loro lavoro giusto, fino a quando non sono stati smentiti. Un test unitario che dimostra che la chiamata WCF corretta non richiede effettivamente l'attraversamento del proxy del servizio e non è necessario verificare che una particolare chiamata del servizio WCF funzioni correttamente in un test dell'unità (indipendentemente dal fatto che funzioni o non dipende da variabili specifiche dell'ambiente che possono essere perfette in un ambiente di test locale ma non nel build-bot, o negli ambienti QA, Staging o UAT: è qui che l'integrazione di livello superiore, l'AAT e il test manuale hanno ancora valore) .

In quasi tutti gli altri casi, una metodologia test-first ha un valore significativo nel far rispettare i requisiti e YAGNI, prevenendo la regressione, identificando i conflitti dei requisiti, ecc. Anche nei casi di codice "banale", che verifica che "sì, questa proprietà fa restituisco ancora questo valore e quindi puoi fidarti che in altri test "ha valore per me come sviluppatore.

    
risposta data 07.05.2012 - 18:01
fonte
18

Esiste un compromesso tra il costo della scrittura dei test unitari e il valore aggiunto. Trascurare questo rischio la possibilità di superare i test .

blueberryfields toccati su una variabile che influenza il valore dei test unitari: stabilità del progetto (o ritmo di sviluppo). Mi piacerebbe ampliarlo.

Il valore di avere test unitari segue approssimativamente il seguente grafico (yay, MS Paint!):

  1. Nellaprimazona,ilcodiceèinstabilealpuntocheitestdiunitàspessodevonoessereriscrittiointeramentescartati.Questopotrebbeessereunprototipochesainonsaràusato.Oppurepotrebbeessereunprogettoincuisiènuoviallinguaggiooalframeworkdiprogrammazione(espessosihabisognodiripeteregrandiquantitàdicodice).

    Itestunitarisonobuoniperilrefactoringalivellodimodulo(cioècambiandofunzioni).Ilproblemaèquandoilcodiceèinstabilealivellodiarchitettura,incuiinterimodulipotrebberoessereriscritti,rimossiocompletamenteridisegnati.Itestunitaridevonoquindiesseremodificati/rimossi/aggiunti,ilcheèunonere.

    Inquestafase,limitandoatestdiintegrazionealivellodisistema,oanchetestmanualeèunapprocciomigliore(qualesiscegliedinuovodipendedalcostodiscritturadeltestrispettoalvalorechesiottiene).

  2. Itestunitariaggiungonoilmaggiorvalorenellasecondazona,doveilcodicediventastabilesopraillivellodelmodulo,manonancoraallivellodelmodulo.Sehaiunabasedicodicestabileestaiaggiungendounmodulochehaun'altaprobabilitàdirimanere,questoèquandoiltestunitarioèunagrandevittoria.

  3. Ancheitestunitariinizianoadaveremenovalorequandolastabilitàdelcodicesottotestèmoltoalta.Testdiunsemplicewrapperdiunafunzionedilibreriastandardèunesempioincuiiltestdell'unitàèeccessivo.

    Seunpezzodicodicechestaiscrivendoprobabilmentenonavràpiùbisognodicambiare,eseisicurodiavercapitobene(forseèsupersemplice?),c'èmenovaloreneltest.

Iltestdell'unitàdiventautilequandol'utilitàèmaggioredelcosto,comemostratonelgraficosottostantenellazonaII.

Questa linea di costo potrebbe essere a diversi livelli per persone diverse (linea 1 vs linea 2). Se sei nuovo nel framework di test usato in un progetto, questo aumenta il livello e rende l'utilità net meno. Un costo più elevato (linea 2) riduce la gamma di test unitari appropriata.

La linea di costo non deve necessariamente essere piatta. Soprattutto quando si considerano altre variabili come la dimensione del progetto e se esiste già una struttura di test per il progetto, potrebbe essere così.

    
risposta data 12.04.2017 - 09:31
fonte
11

Where are unit tests least valuable?

Dovresti scrivere test unitari solo per codice logico. La definizione del codice logico è la seguente:

Il codice logico è qualsiasi parte di codice che ha una sorta di logica in esso, per quanto piccolo possa essere. È un codice logico se ha uno o più dei seguente: un'istruzione IF, un ciclo, un passaggio o un caso, calcoli o qualsiasi altro tipo di codice decisionale.

If that's the end of the spectrum where unit testing is most valuable, then what's the other end?

  • Il codice strettamente accoppiato non può essere facilmente testato. A volte non può essere provato affatto. Ad esempio i ASP.NET moduli web sono un incubo e talvolta impossibili da testare, al contrario di ASP.NET MVC che è stato creato pensando ai test unitari.

  • Potrei scegliere di non scrivere test per progetti molto piccoli e semplici. Questo è perfettamente giustificabile in un mondo con tempo e risorse limitati. Sì, è rischioso, ma è perfettamente accettabile quando l'azienda per cui lavori ha un tempo di commercializzazione limitato.

What situations would you not bother? Where would the effort of maintaining tests not be worth the cost?

Una volta che i test unitari sono stati effettuati, i loro costi di manutenzione diventano insignificanti. I test unitari con copertura di codice elevato ti danno un senso di sicurezza che il sistema si comporta come te lo aspetti. Lo stesso vale per i test di integrazione, ma questa non è una tua domanda.

La mia risposta si basa sui seguenti presupposti:

  • Conoscete la differenza tra unità, integrazione e test funzionali.
  • Sei esperto in uno dei framework di test unitari e ti ci vuole pochissimo sforzo per scrivere un test unitario.
  • Non ti sembra che stai facendo un lavoro extra quando stai scrivendo test unitari.

Riferimento: Art of Unit Test

    
risposta data 04.05.2012 - 21:58
fonte
9

Kent Beck (l'uomo dietro l'idea di Unit Testing) dice che va bene non scrivere Test unitari quando si lavora su un'idea (ad esempio il prototipo) che si potrebbe buttare via (se si decide di non lavorare più avanti). Al contrario, se scrivi il tuo prototipo e decidi di farlo, Unit Testing sarà utile per tutti i motivi trattati nelle risposte precedenti.

    
risposta data 05.05.2012 - 22:34
fonte
7

Dovresti davvero testare qualsiasi codice che intendi eseguire in più di 1 occasione.

Se intendi eseguirlo una volta e poi buttarlo via, i test potrebbero non essere utili, anche se il dominio è complesso, potrei comunque scrivere i test per aiutarmi con la mia progettazione e implementazione.

Altrimenti, anche se l'unica cosa che fanno i test è confermare che le tue supposizioni sono ancora corrette, sono preziose. E qualsiasi codice che duri più di una singola sessione avrà bisogno di modifiche, a quel punto i test si ripagheranno 10 volte.

    
risposta data 03.05.2012 - 12:57
fonte
6

Non ho idea di non necessario , ma cercherò di farlo quando penso che i Test di Unità siano inappropriati in quanto aggiungono un costo senza un vantaggio proporzionale:

Se la nostra organizzazione / team di sviluppo non sta effettuando alcun test unitario, a meno che non siate in grado di convincere i vostri colleghi sviluppatori di eseguire, testare (e anche creare autonomamente) test unitari, i test che create non vanno essere gestito e mantenuto. (Questo implica che stai lavorando su un software insieme a qualcun altro.)

Non tutti stanno facendo test unitari, a volte sono mal supportati dalla cultura del team locale, e in tali ambienti è necessario innanzitutto metterli in atto per la maggior parte degli sviluppatori e probabilmente anche per il processo di costruzione ("[continua ] integrazione ") prima di iniziare effettivamente a scrivere test unitari ha senso.

Data la pressione del tempo e le date di consegna e il "tuo" parente in piedi con il team - il tempo rimanente fino a quando scrivere i test unitari ha senso può essere facilmente mesi o anni.

    
risposta data 03.05.2012 - 13:55
fonte
4

A volte non hai tempo per il test unitario. Va bene.

Esistono vincoli esterni e potresti non sentire la necessità di test in un dato momento, poiché potresti pensare di avere una presa ferma sull'intero stato del sistema e sapere come si evolveranno i cambiamenti.

Ma credo ancora che dovresti sentirti un po 'colpevole a riguardo. Quindi, quando le cose iniziano a crollare, saprai che è perché: "oh, sì, non sto testando le cose, iniziamo i test."

Prima di quel momento, il senso di colpa ti aiuterà a evitare certe scelte architettoniche che ti impedirebbero di essere in grado di automatizzare i test di codice in seguito.

    
risposta data 03.05.2012 - 14:40
fonte
2

Il costo non è nel mantenere i test, ma piuttosto nel non mantenere il codice funzionante. Se divorzi dai test e dall'implementazione, stai assumendo che ciò che scrivi funzionerà senza il beneficio della prova. I test ti danno quella prova e la sicurezza di mantenere il codice con il passare del tempo. Certo, potresti pensare di non rivisitare mai quell'app che pensavi fosse un lancio, tuttavia la realtà è che ogni volta che passi a scrivere software è un investimento che il tuo datore di lavoro non vuole trattare con leggerezza. Ammettiamolo, gli sviluppatori di software in genere non costano poco, e il tempo speso per il codice da buttar via è denaro semplicemente bruciato al tuo datore di lavoro.

Se stai riscontrando un problema, scrivendo alcune righe di codice per vedere come funziona qualcosa o semplicemente lanciando un esempio per Programmers.SE, allora è davvero un caso di creare qualcosa che intendi completamente buttare via una volta ho soddisfatto la tua comprensione di un problema. In questi casi, il test unitario può essere di ostacolo al compito e può essere tranquillamente escluso. In tutti gli altri casi, tuttavia, direi che il test è sempre appropriato, anche se il programma sembra relativamente irrilevante, e dovresti sempre puntare a scrivere software su uno standard professionale con sufficiente supporto per ridurre la difficoltà a mantenere il codice nel futuro.

    
risposta data 03.05.2012 - 12:54
fonte
1

La quantità e la qualità dei test unitari da eseguire in un progetto sono direttamente proporzionali al ritmo di sviluppo e alla stabilità richiesta del prodotto.

Da un lato, per uno script singolo, una demo banale o in un ambiente di avvio rapido durante le primissime fasi, è improbabile che i test unitari siano importanti o utili per qualsiasi cosa. Sono quasi sempre, quasi certamente, uno spreco di tempo e risorse.

Dall'altra parte, quando si scrive software per controllare i pacemaker, o le navi missilistiche pilota, o quando si lavora per mantenere sistemi software stabili e altamente complessi (diciamo, un compilatore con una strong adozione attraverso il multiverso) più livelli di unità test e altre coperture sono fondamentali.

[Ci sono un sacco di altri fattori specifici della situazione che ciascuno contribuisce in un modo o nell'altro, come la dimensione della tua squadra, il tuo budget, il talento dei tuoi sviluppatori, la tua strategia di sviluppo software preferita, ecc ... In generale, e al più alto livello di astrazione, trovo che questi due facciano la differenza più grande]

    
risposta data 04.05.2012 - 00:01
fonte
0

Dal mio punto di vista, i prototipi di prodotto / codice non richiedono test poiché vengono spesso forniti utilizzando un processo completamente diverso e per scopi completamente diversi rispetto a un prodotto finito.

Immagina questo scenario comune. Hai una sorta di tecnologia per la quale la tua azienda è famosa, il tuo team di vendita o un dirigente capo va a un cliente ed è in grado di venderli un prodotto diverso che sfrutta la tua tecnologia. Lo vendono lì e poi e promettono al cliente che vedranno una versione beta in un mese. Non hai nulla, nemmeno un team di sviluppo.

Che cosa accadrà dopo si progetta rapidamente una soluzione basata sui punti concordati / venduti al cliente, si riunisce un team di ingegneri (spesso star) e si inizia a scrivere codice. Sarebbe ovviamente l'ideale se le tue date non scivolassero (lo fanno sempre) e sei riuscito a scrivere codice in tre settimane anziché in quattro. In questo caso hai una settimana in più e se sei riuscito a garantire il tempo di una squadra di QA per questa settimana, lo testerai. In realtà non avrai una settimana in più e / o il tuo team di QA è prenotato per altri due mesi a supporto di altre consegne di prodotti. Inoltre non avrai alcuna specifica di progettazione, quindi il team di QA non avrà alcuna idea di cosa si suppone stia testando. Quindi finisci per consegnare quello che hai scritto con un po 'del tuo test del fumo, che non è un vero test in quanto tale, semplicemente perché non sei qualificato per testare il tuo codice. Il più grande fattore qui è che il client vedrà alcune delle funzionalità promesse molto rapidamente. Se il tuo prototipo fa il lavoro, allora sei di nuovo al tavolo da disegno, dove hai progettato e pianificato la versione 1.0 effettiva - questa volta correttamente.

Per quanto riguarda i test unitari, sono buoni per mantenere determinati contratti (prometto che il mio codice lo farà, se non lo fa - è rotto). In caso di prototipazione, potresti non interessarti troppo ai contratti, perché spesso i tuoi prototipi non diventeranno vivi per diventare la versione 1.0, sia perché il cliente è andato via, sia perché hai finito per sviluppare la tua versione 1.0 utilizzando diverse tecnologie / strumenti. Un esempio qui sarebbe un prototipo di sito Web veloce scritto da PHP in un mese a un mese da PHP, quindi assemblare un team per riscriverlo in JEE. Anche il database spesso non sopravviverà a questo cambiamento.

    
risposta data 03.05.2012 - 12:43
fonte
0

Dovresti scrivere dei test unitari quando la comprensione logica richiesta per mantenere o estendere o comunicare la logica dell'applicazione senza difetti eccede (o probabilmente supererà in futuro) la capacità del membro meno esperto del tuo team di soddisfarlo comprensione.

Fondamentalmente dipende da quanto puoi tenere nella tua testa in una volta. Da soli potresti avere più fiducia che puoi codificare (con piena consapevolezza dell'impatto delle tue modifiche) fino a quando non si raggiunge una certa complessità. Fino a quel momento i test unitari sono una distrazione, un ostacolo e ti rallenteranno. In una squadra, la soglia sarà molto più bassa quindi hai praticamente bisogno di test unitari per contrastare la stupidità di gruppo. Se raccogli un progetto senza prova da qualcun altro (o ti sei dimenticato di un progetto da un po 'di tempo fa) vorrai scrivere dei test unitari prima di cambiare qualcosa perché la tua comprensione sarà zero.

Nota: scrivere meno codice e praticare YAGNI, mantiene la complessità e quindi il numero di test unitari richiesti.

    
risposta data 03.05.2012 - 14:14
fonte
0

I test unitari sono belli e tutti, ma in sistemi complicati con molte "parti mobili", in realtà non testano molto.

Come sappiamo, i test unitari assicurano che l'input X dato per un'unità, si ottiene l'uscita Y dove X è tutto l'input appropriato e Y è tutto l'output appropriato. Tuttavia, trovo che la maggior parte del codice faccia ciò che lo sviluppatore pensava dovrebbe ... ma non è necessario che cosa dovrebbe effettivamente fare.
(Potresti pensare ad esso come una pistola: una pistola ha un gruppo di pezzi di precisione fabbricati separatamente e poi assemblati.) Non importa se ciascuna particolare parte è testata bene per la funzionalità se la pistola esplode quando effettivamente sparata. : Non so nulla di armi da fuoco (:)

In questo caso, abbiamo bisogno di test di sistema effettivi in un ambiente di produzione del modello. Dal momento che la funzionalità viene testata comunque, il valore dei test unitari è leggermente diminuito.

Tuttavia, i test unitari sono ancora validi in questo caso perché garantiscono che la funzionalità che si desidera mantenere invariata rimane in effetti invariata. Questo è abbastanza importante perché ti dà sicurezza per le aree del sistema che necessitano di test mirati.

    
risposta data 03.05.2012 - 17:12
fonte
-1

I test unitari IMO sono inappropriati (non inutili!) in qualsiasi base di codice in cui richiederebbero tonnellate di ore di refactoring o addirittura una riscrittura totale per introdurre test unitari, perché sarebbe una vendita molto difficile da gestire per consentire quella ripartizione temporale.

    
risposta data 03.05.2012 - 22:46
fonte
-1

In un'organizzazione più piccola e veloce, trovo che gli sviluppatori siano così pressati da rimanere produttivi e muoversi velocemente che spesso non si preoccupano di testare i propri cambiamenti.

Abbiamo una politica generale che stabilisce che se apporti una modifica (che si tratti di una correzione o di un miglioramento) lo sviluppatore dovrebbe testarlo prima di inviare il codice per ulteriore controllo qualità.

In realtà non scriviamo test unitari per la maggior parte delle istanze perché i nostri schermi sono progettati principalmente in modo tale che se viene apportata una modifica sullo schermo, il resto della logica deve essere attraversato per scoprire se il il cambiamento ha avuto esito positivo a prescindere.

Trovo imperativo che lo sviluppatore faccia il suo test, che sia documentato o meno, perché sono quelli che meglio sanno dove possono essere i potenziali punti deboli nella logica.

Quindi direi che, anche se non si scrivono test unitari per ogni piccola parte del sistema, il test del buon senso dovrebbe essere fatto a prescindere.

    
risposta data 12.05.2012 - 16:52
fonte

Leggi altre domande sui tag