Perché i miei test unitari sono così costosi? [duplicare]

6

Sono uno sviluppatore Java, che lavora su un piccolo progetto. Siamo tre persone nel team, abbiamo un budget per 3 mesi di codifica (+ un po 'di tempo per l'analista, il project manager e il team di QA). È un piccolo progetto, il budget è davvero limitato. C'è qualche supporto nella nostra organizzazione per fare i test unitari, ma non ho incontrato nessun esperto in questo settore. Motivato da libri e discussioni, ho iniziato a fare i test unitari. Ho una certa esperienza limitata con framework e approcci, quindi non testo tutti i getter, mi concentro sul codice aziendale, utilizzo il plugin Mockito e MoreUnit Eclipse per generare lo scheletro e Mock. Progetto il mio codice in anticipo, utilizzo un sacco di schemi di progettazione, mantengo pulito il mio codice, con metodi brevi, rispetto la Single Responsibility Principe e ho metodi molto più pubblici che privati. Non è perfetto, ma è il meglio che posso fare dopo 5 anni di esperienza commerciale in un'azienda e in un'azienda di medie dimensioni.

Quindi perché fare test unitari mi prende la stessa quantità di tempo, o anche più alto, di codificare codice produttivo? Dopo gli ultimi due giorni di test unitari ho trovato solo un piccolo bug e non è venuto dai test, l'ho trovato solo casualmente mentre cercavo nel codice di produzione. Dove sono i benefici di cui parlano le persone? Ogni refactoring ha causato solo il lancio di test unitari esistenti e non mi hanno mai detto se avessi influenzato il resto del sistema. Ogni test di classe I ha preso in giro l'ambiente circostante, quindi se cambio una classe, non inciderà sugli altri test e non saprò se ho incasinato il sistema con il mio resto.

Cosa mi manca? Sto sbagliando?

Modifica: per aggiungere alcuni numeri, trascorro circa l'80% del tempo progettando e codificando, e il 20% da test unitari, quindi solo una piccola parte del mio codice è coperta da test. Provo a fare un test unitario di 1,5 mesi, di solito dopo aver terminato alcune funzionalità e testare approssimativamente la mia macchina di sviluppo locale.

    
posta Michal 07.04.2015 - 22:03
fonte

6 risposte

13

Se prima provi le cose manualmente attraverso un'interfaccia utente, finché non trovi più bug e scrivi successivamente i test unitari, non è molto sorprendente che quei test unitari non rivelino molti bug. Probabilmente stai solo automatizzando cose che hai già fatto manualmente, ma non codifichi molti casi di test che non facevano già parte dei test manuali.

I test unitari e altri test automatici mostreranno il loro valore molto più chiaro quando

  • può usarli per testare cose che non puoi facilmente testare attraverso l'interfaccia utente
  • quando sviluppi componenti di piccole dimensioni e indipendenti dall'UI e li collaudi attraverso il test di unità senza effettivamente avendo codificato l'interfaccia utente per loro
  • quando la tua applicazione diventa più grande e dopo il rilascio n. 25 o successivi si nota che ripetere ripetutamente gli stessi test attraverso l'interfaccia utente diventa noioso
  • quando sviluppi software senza alcuna interfaccia utente o in cui l'interfaccia utente ti consente di accedere solo a una piccola parte del sistema direttamente (ad esempio, un'interfaccia utente simile a google).
  • quando fai TDD, dove devi scrivere test di unità, altrimenti non puoi nemmeno iniziare a scrivere codice

Quindi, se non hai intenzione di passare alla codifica in stile TDD, e fintanto che stai scrivendo le applicazioni dell'interfaccia utente in anticipo, con la maggior parte delle funzionalità direttamente accessibili tramite l'interfaccia utente, non stupirti che l'automazione dei test di qualsiasi tipo sia un investimento aggiuntivo, che può sembrare noioso e non mostrerà immediatamente il suo valore reale.

    
risposta data 07.04.2015 - 23:04
fonte
11

Una cosa da ricordare sui test è che lo farai in entrambi i modi . Sia che tu stia stampando le variabili dell'applicazione sullo schermo, utilizzando un debugger per ispezionare lo stato dell'applicazione o semplicemente verificando visivamente l'output finale dell'input dell'applicazione, alla fine della giornata, avrai passato un bel po 'di tempo a commentare codice, magari impostando i breakpoint o eseguendo altre attività di test nel tentativo di verificare che il codice funzioni all'interno delle regole aziendali previste. La domanda da porsi è, puoi codificare i frutti del tuo lavoro in un processo ripetibile, o semplicemente eliminare / commentare il codice di prova effimero una volta che tutto sembra funzionare correttamente?

I vantaggi dei test diventano più visibili più a lungo il progetto va avanti. Quando si progetta per la prima volta un software, potrebbe sembrare che i test non siano necessari perché è facile immaginare molti casi limite nella propria mente, tuttavia, poiché un progetto matura e diventa più complesso, alla fine si incontreranno problemi imprevisti che una volta risolti potrebbe inavvertitamente interrompere qualcosa che hai già risolto e testato manualmente. Se è passato molto tempo o qualcun altro finisce per sistemare il bug, non ti accorgi nemmeno che il tempo è stato sprecato ripercorrendo il percorso del problema, supponendo che il bug sia stato addirittura riscoperto. I test unitari ti permettono di andare avanti in tutta sicurezza sapendo che stai costruendo sulla base di una fondazione che funziona come specificato. Creare test significa che ogni bug che correggi è anche risolto per sempre , non deve essere reintrodotto inavvertitamente in un prodotto live attraverso successive modifiche al codice da parte tua o di qualcun altro del team.

Scrivere test a volte ritiene come più lavoro perché puoi guardare il test e identificarlo come il prodotto del tuo tempo trascorso lavorando durante una sessione, tuttavia, ogni sviluppatore esperto sa che a volte si può spendere ore cercando di eseguire il debug di quello che sembra un problema molto semplice, solo senza test, semplicemente attribuiamo il tempo impiegato per "debugging necessario" piuttosto che "scrivere test tutto il giorno". Non si può dare la colpa a un bug che non esiste più, ma è naturale guardare una serie di test irrisori e chiedersi perché non si ha più da mostrare per il proprio tempo quando in realtà entrambi i risultati sono gli stessi.

Ora, questo non vuol dire che non sia possibile perdere tempo a manipolare strumenti di prova o scrivere test inefficienti o non necessari. Ci vuole un po 'di tempo per provare a scrivere test appropriati, ma nella mia esperienza il modo migliore per evitare questi problemi è pianificare in anticipo . Definire una specifica che funge da definizione per una baseline o un prototipo della propria applicazione funzionanti e testare le specifiche. Se trovi che le specifiche cambiano continuamente e stai sempre buttando fuori i test, probabilmente significa che il tuo design è difettoso o che lo spazio del problema non è ben compreso. La chiave per scrivere test di successo è avere fiducia che i test rappresentino veramente il prodotto che si desidera produrre.

    
risposta data 07.04.2015 - 23:29
fonte
7

Why are my unit tests so expensive?

Per la stessa ragione, il divorzio è così costoso:

Ne vale la pena.

Nella mia esperienza (bizdev, C # / Java da oltre un decennio a questa parte), scrivere test di unità per il codice richiede circa la metà del tempo di scrittura del codice stesso, quindi il 33% del tempo totale di codifica. Alcune cose saranno di più. Alcune cose saranno meno. Quando stai solo imparando a scrivere test unitari, sarà più lento della codifica "normale". Questo (nella mia esperienza) fornisce il punto debole per la maggior parte del codice tra il tempo speso e le prove efficaci. Di solito è una buona copertura del codice del 70-80%, dare o avere. Alcuni ambienti potrebbero richiedere una qualità più rigorosa. Meno potrebbe averne bisogno di meno.

Potrebbe sembrare un sacco, ma avere i test ti fa risparmiare tempo altrimenti passeresti a rintracciare bug QA, fare patch, testare manualmente o soffrire di codice che non puoi rifattorizzare efficacemente.

so if I change one class, it will not affect the other tests and I won't know if I messed up the system by my change.

Certo che lo farai, se prendi in giro le interazioni tra le tue classi correttamente. Se hai cambiato la tua classe e i tuoi test di unità passano (tutti gli input sono gestiti come previsto e forniscono risultati legali / previsti), allora non puoi influenzare il resto del sistema, poiché l'interfaccia tra la tua classe e il mondo esterno è intatta e ben testato.

    
risposta data 07.04.2015 - 22:36
fonte
1

La chiave è testare l'intenzione del tuo codice.

In questo modo, anche se rifattori il modo in cui la tua intenzione viene implementata, sarai comunque in grado di avere un test unitario valido perché è sempre la stessa intenzione.

Come hai detto tu stesso, se disponi di risorse limitate, allora fai ciò che è più importante e quella sarebbe la logica aziendale.

Inoltre, non dimenticare i test di accettazione e integrazione poiché potrebbero eliminare la necessità di testare singolarmente ogni singolo strato.

Se stai seguendo tutte queste best practice, come hai menzionato sopra, allora scrivere test unitari non dovrebbe essere così difficile - forse sei solo nuovo nel paradigma del testing e con la pratica accelerai e sarai in grado di produrre codice più rapidamente con una qualità migliore.

    
risposta data 07.04.2015 - 22:14
fonte
1

Potrebbe essere necessario più tempo per scrivere codice completo con test unitari. In effetti probabilmente lo farà. Ciò che rende un modo più produttivo di lavorare per l'organizzazione nel suo insieme sono tutte le cose che non accadono più avanti sulla linea, e in particolare non succede ad altre persone, quando hai il tuo codice armato con una batteria piena di test. Meno tester manuali necessari per raggiungere lo stesso livello di qualità. Meno chiamate di assistenza di emergenza costose. Meno clienti che silenziosamente scivolano su un concorrente senza avvisarti di bug. Meno tempo speso per portare un nuovo collega alla velocità, perché il tuo codice di prova documenta cosa dovrebbe fare il codice di produzione. Meno tempo impiegato per riparare i danni causati da un nuovo substandard collega.

Questa visione della produttività è difficile da misurare, ed è per questo che il management e i programmatori spesso ricorrono istintivamente a misurare il tempo necessario per passare dallo schermo bianco a qualcosa che funziona principalmente, il più delle volte.

    
risposta data 08.04.2015 - 09:49
fonte
1

Il tipo di test delle unità che devi fare per trovare bug nel codice già funzionante è molto diverso dal tipo usato come scaffold durante la creazione o la modifica del codice. Solo quest'ultimo è TDD / BDD. E, come è un po 'più recente, tende ad essere quello che viene discusso in articoli e blog. A volte fino al punto in cui le persone hanno l'impressione che sia "ciò che devi fare", al contrario di "ciò che devi fare per ...".

La giustificazione di fondo per TDD, al contrario di altri approcci di progettazione, è che parte dell'impalcatura di progettazione si attacca e diventa test utili. Indipendentemente dal fatto che tu compri o meno, erigere impalcature dopo aver terminato lo sviluppo non sarà praticamente mai utile.

Alcuni strumenti, come JUnit e mockito, sono comuni ad entrambi gli approcci (anche se l'uso eccessivo di mock porter rapidamente a test che non hanno valore se non quello di impalcature). Altri strumenti, come quickcheck e tcases sono inutili come impalcature, ed eccellenti per la creazione di bug.

Indipendentemente dal fatto che si utilizzi o meno il test dell'unità durante il TDD, qualsiasi unità che si esegue dopo aver completato il codice dovrebbe essere orientata verso l'individuazione dei bug. A seconda dei compromessi di affidabilità / costo, a volte è perfettamente razionale sostituire selettivamente i test di scaffold creati durante lo sviluppo con test di bug bug.

    
risposta data 08.04.2015 - 12:31
fonte

Leggi altre domande sui tag