Perché usare JUnit per i test?


131

Forse la mia domanda è nuova, ma non riesco davvero a capire le circostanze in cui vorrei usare ?

Che io scriva applicazioni semplici o più grandi, le collaudo con le System.outdichiarazioni e mi sembra abbastanza facile.

Perché creare classi di test con JUnit, cartelle non necessarie nel progetto se dobbiamo ancora chiamare gli stessi metodi, controllare cosa restituiscono e quindi abbiamo un sovraccarico di annotare tutto?

Perché non scrivere una classe e provarla subito con System.outma non creare classi di prova?

PS. Non ho mai lavorato su grandi progetti che sto solo imparando.

Qual è lo scopo?



7
Sei consapevole del fatto che ogni volta che modifichi qualcosa nel tuo programma, tutti i tuoi precedenti lavori di esame manuale dell'output vengono invalidati e devi rifarli dall'inizio?
Thorbjørn Ravn Andersen,

Non solo "test", ma anche "test intelligenti" è molto importante. Ecco un bell'esempio: wp.me/prMeE-11
akcasoy

Risposte:


139

Questo non è test, è "guardare manualmente l'output" (noto nel biz come LMAO). Più formalmente è noto come "cercare manualmente output anomali" (LMFAO). (Vedi nota sotto)

Ogni volta che si modifica il codice, è necessario eseguire l'app e LMFAO per tutto il codice interessato da tali modifiche. Anche nei piccoli progetti, questo è problematico e soggetto a errori.

Ora scala fino a 50k, 250k, 1m LOC o più e LMFAO ogni volta che apporti una modifica del codice. Non solo è spiacevole, è impossibile: hai ingrandito le combinazioni di input, output, flag, condizioni ed è difficile esercitare tutti i rami possibili.

Peggio ancora, LMFAO potrebbe significare visitare pagine su pagine di app Web, eseguire report, analizzare milioni di linee di log su decine di file e macchine, leggere e-mail generate e consegnate, controllare messaggi di testo, controllare il percorso di un robot, riempire una bottiglia di soda, aggregando i dati di un centinaio di servizi web, controllando la pista di controllo di una transazione finanziaria ... hai avuto l'idea. "Output" non significa alcune righe di testo, "output" significa comportamento di sistema aggregato.

Infine, i test unitari e comportamentali definiscono il comportamento del sistema. I test possono essere eseguiti da un server di integrazione continua e controllati per correttezza. Certo, anche così System.out, ma il server CI non saprà se uno di essi è sbagliato - e se lo fa, sono test unitari e potresti anche usare un framework.

Non importa quanto riteniamo di essere bravi, gli umani non sono buoni framework di unit test o server CI.


Nota: LMAO sta testando, ma in senso molto limitato. Non è ripetibile in alcun modo significativo in un intero progetto o come parte di un processo. È simile allo sviluppo incrementale in un REPL, ma mai formalizzare quei test incrementali.


3
-1 per la prima frase, che è completamente e assolutamente falso.
Michael Borgwardt,

50

Scriviamo test per verificare la correttezza del comportamento di un programma.

Verificare la correttezza del comportamento di un programma ispezionando il contenuto delle dichiarazioni di output usando i propri occhi è un processo manuale o, più specificamente, visivo .

Potresti discuterne

l'ispezione visiva funziona , controllo che il codice faccia quello che deve fare, per questi scenari e una volta che riesco a vedere che è corretto siamo pronti.

Ora, prima di tutto, è fantastico che tu sia interessato a sapere se il codice funziona correttamente. È una buona cosa. Sei davanti alla curva! Purtroppo, ci sono problemi con questo come approccio.

Il primo problema con l'ispezione visiva è che sei un brutto incidente di saldatura lontano dal non poter mai più verificare la correttezza del codice.

Il secondo problema è che la coppia di occhi utilizzata è strettamente accoppiata al cervello del proprietario degli occhi. Se l'autore del codice possiede anche gli occhi utilizzati nel processo di ispezione visiva, il processo di verifica della correttezza dipende dalla conoscenza del programma interiorizzato nel cervello dell'ispettore visivo.

È difficile per un nuovo paio di occhi entrare e verificare la correttezza del codice semplicemente perché non sono associati al cervello del programmatore originale. Il proprietario del secondo paio di occhi dovrà conversare con l'autore originale del codice per comprendere appieno il codice in questione. La conversazione come mezzo per condividere la conoscenza è notoriamente inaffidabile. Un punto controverso se il Coder originale non è disponibile per i nuovi occhi della coppia. In quel caso il nuovo paio di occhi deve leggere il codice originale.

Leggere il codice di altre persone che non è coperto dai test unitari è più difficile della lettura del codice a cui sono associati test unitari. Nella migliore delle ipotesi leggere il codice di altre persone è un lavoro complicato, nella peggiore delle ipotesi questo è il compito più turgido nell'ingegneria del software. C'è una ragione per cui i datori di lavoro, quando pubblicizzano offerte di lavoro, sottolineano che un progetto è greenfield (o nuovo di zecca). Scrivere codice da zero è più semplice che modificare il codice esistente e quindi rendere il lavoro pubblicizzato più attraente per i potenziali dipendenti.

Con i test unitari dividiamo il codice nelle sue parti componenti. Per ogni componente abbiamo quindi stabilito la nostra stalla dichiarando come dovrebbe comportarsi il programma . Ogni unit test racconta una storia di come quella parte del programma dovrebbe agire in uno scenario specifico. Ogni unit test è come una clausola di un contratto che descrive cosa dovrebbe accadere dal punto di vista del codice client.

Ciò significa quindi che un nuovo paio di occhi ha due filoni di documentazione dal vivo e accurata sul codice in questione.

Innanzitutto hanno il codice stesso, l'implementazione, il modo in cui il codice è stato fatto ; in secondo luogo hanno tutte le conoscenze che il programmatore originale ha descritto in una serie di dichiarazioni formali che raccontano la storia di come dovrebbe comportarsi questo codice .

I test unitari catturano e descrivono formalmente le conoscenze possedute dall'autore originale durante l'implementazione della classe. Forniscono una descrizione di come si comporta quella classe quando viene utilizzata da un client.

È corretto mettere in dubbio l'utilità di farlo perché è possibile scrivere test unit che sono inutili, non coprono tutto il codice in questione, diventano obsoleti o obsoleti e così via. Come possiamo garantire che i test unitari non solo imitino ma migliorino il processo di un autore consapevole e coscienzioso che ispeziona visivamente le dichiarazioni di output del loro codice in fase di esecuzione? Scrivi prima il test unitario, quindi scrivi il codice per far passare quel test. Quando hai finito, lascia che i computer eseguano i test, sono veloci, sono bravi a svolgere attività ripetitive e sono ideali per il lavoro.

Garantire la qualità dei test rivedendoli ogni volta che si sfiora il codice che testano ed eseguono i test per ogni build. Se un test ha esito negativo, risolverlo immediatamente.

Automatizziamo il processo di esecuzione dei test in modo che vengano eseguiti ogni volta che realizziamo un progetto. Automatizziamo anche la generazione di rapporti sulla copertura del codice che descrivono in dettaglio quale percentuale di codice è coperta ed esercitata dai test. Ci impegniamo per percentuali elevate. Alcune società impediranno il check-in delle modifiche al codice per il controllo del codice sorgente se non dispongono di test unitari sufficienti scritti per descrivere eventuali cambiamenti nel comportamento del codice. In genere un secondo paio di occhi esaminerà le modifiche al codice insieme all'autore delle modifiche. Il revisore esaminerà le modifiche assicurando che le modifiche siano comprensibili e sufficientemente coperte dai test. Quindi il processo di revisione è manuale, ma quando i test (test di unità e integrazione e, eventualmente, test di accettazione da parte dell'utente) superano questo processo di revisione manuale, diventano parte del processo di compilazione automatica. Questi vengono eseguiti ogni volta che viene registrato un cambiamento. A il server esegue questa attività come parte del processo di compilazione.

I test eseguiti automaticamente, mantengono l'integrità del comportamento del codice e aiutano a impedire che future modifiche alla base di codice interrompano il codice .

Infine, la fornitura di test consente di ricodificare in modo aggressivo il codice poiché è possibile rendere sicuri i miglioramenti di codice di grandi dimensioni nella consapevolezza che le modifiche non interrompono i test esistenti.

C'è un avvertimento per Test Driven Development e cioè che devi scrivere codice con un occhio per renderlo testabile. Ciò comporta la codifica di interfacce e l'utilizzo di tecniche come l'iniezione di dipendenza per creare istanze di oggetti collaborativi. Scopri il lavoro di Kent Beck che descrive molto bene TDD. Cerca la codifica per le interfacce e studia


13

Quando esegui un test utilizzando qualcosa come System.out, stai testando solo un piccolo sottoinsieme di possibili casi d'uso. Questo non è molto accurato quando si ha a che fare con sistemi che potrebbero accettare una quantità pressoché infinita di input diversi.

I test unitari sono progettati per consentire di eseguire rapidamente test sull'applicazione utilizzando un set molto ampio e diversificato di input di dati diversi. Inoltre, i migliori test unitari tengono conto anche dei casi limite, come gli input di dati che si trovano proprio al limite di ciò che è considerato valido.

Per un essere umano testare tutti questi diversi input potrebbe richiedere settimane mentre potrebbero volerci minuti per una macchina.

Pensala in questo modo: non stai "testando" qualcosa che sarà statico. Molto probabilmente la tua applicazione subirà continue modifiche. Pertanto, questi test unitari sono progettati per essere eseguiti in punti diversi nel ciclo di compilazione o distribuzione. Forse il più grande vantaggio è questo:

Se rompi qualcosa nel tuo codice, lo saprai subito , non dopo averlo distribuito, non quando un tester QA rileva un bug, non quando i tuoi clienti hanno annullato. Avrai anche una migliore possibilità di risolvere immediatamente il problema tecnico , poiché è chiaro che la cosa che ha spezzato la parte del codice in questione molto probabilmente è accaduta dall'ultima compilazione. Pertanto, la quantità di lavoro investigativo richiesta per risolvere il problema è notevolmente ridotta.


9

Ho aggiunto qualche altro System.out NON può fare:

  • Rendi indipendenti tutti i casi di test (è importante)

    JUnit può farlo: ogni volta che viene creata e @Beforechiamata una nuova istanza del test case .

  • Separare il codice di test dalla fonte

    JUnit può farlo.

  • Integrazione con CI

    JUnit può farlo con Ant e Maven.

  • Disporre e combinare facilmente i casi di test

    JUnit può eseguire @Ignoree testare la suite.

  • Risultato facile da controllare

    JUnit offre molti metodi Assert ( assertEquals, assertSame...)

  • Mock e stub ti concentrano sul modulo di test.

    JUnit può fare: l'uso di mock e stub consente di impostare l'apparecchiatura corretta e di concentrarsi sulla logica del modulo di test.


9

I test unitari assicurano che il codice funzioni come previsto. Sono anche molto utili per garantire che il codice funzioni ancora come previsto nel caso in cui sia necessario modificarlo in seguito per creare nuove funzionalità per correggere un bug. Avere un'elevata copertura di test del codice consente di continuare a sviluppare funzionalità senza dover eseguire molti test manuali.

Il tuo approccio manuale di System.out è buono ma non il migliore. Questo è un test una volta eseguito. Nel mondo reale, i requisiti continuano a cambiare e la maggior parte delle volte si apportano molte modifiche alle funzioni e alle classi esistenti. Quindi ... non ogni volta che provi il pezzo di codice già scritto.

ci sono anche alcune funzionalità più avanzate come JUnit

Dichiarazioni di asserzione

JUnit fornisce metodi per verificare determinate condizioni, questi metodi in genere iniziano con assert e consentono di specificare il messaggio di errore, il risultato atteso e quello effettivo

Alcuni di questi metodi sono

  1. fail([message])- Lascia che il test fallisca. Potrebbe essere utilizzato per verificare che una determinata parte del codice non venga raggiunta. O per avere un test fallito prima dell'implementazione del codice di test.
  2. assertTrue(true)/ assertTrue(false)- Sarà sempre vero / falso. Può essere utilizzato per predefinire un risultato del test, se il test non è ancora stato implementato.
  3. assertTrue([message,] condition)- Verifica che il valore booleano conditionsia vero.
  4. assertEquals([message,] expected, actual)- Verifica se due valori sono uguali (secondo il equalsmetodo se implementato, altrimenti usando il ==confronto di riferimento). Nota: per gli array, è il riferimento che viene controllato e non il contenuto, utilizzare assertArrayEquals([message,] expected, actual)per quello.
  5. assertEquals([message,] expected, actual, delta) - Verifica se due valori float o double si trovano a una certa distanza l'uno dall'altro, controllati da delta valore.
  6. assertNull([message,] object) - Verifica che l'oggetto sia nullo

e così via. Vedi il Javadoc completo per tutti gli esempi qui .

Suites

Con le suite di test, puoi in un certo senso combinare più classi di test in una singola unità in modo da poterle eseguire tutte in una volta. Un semplice esempio, che combina le classi di test MyClassTeste MySecondClassTestin una Suite chiamata AllTests:

import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;

@RunWith(Suite.class)
@SuiteClasses({ MyClassTest.class, MySecondClassTest.class })
public class AllTests { } 

6

Il vantaggio principale di JUnit è che è automatizzato piuttosto che dover controllare manualmente con le stampe. Ogni test che scrivi rimane nel tuo sistema. Ciò significa che se si apporta una modifica che ha un effetto collaterale imprevisto, il test lo prenderà e fallirà invece di dover ricordare di provare manualmente tutto dopo ogni modifica.


4

JUnit è un framework di unit test per Java Programming Language. È importante nello sviluppo guidato dai test ed è uno di una famiglia di framework di unit test noti collettivamente come xUnit.

JUnit promuove l'idea di "prima test poi codifica", che pone l'accento sull'impostazione dei dati di test per un pezzo di codice che può essere testato prima e quindi può essere implementato. Questo approccio è come "testare un po ', codificare un po', testare un po ', codificare un po' ..." che aumenta la produttività del programmatore e la stabilità del codice del programma che riduce lo stress del programmatore e il tempo dedicato al debug.

Funzionalità JUnit è un framework open source utilizzato per la scrittura e l'esecuzione di test.

Fornisce annotazioni per identificare i metodi di prova.

Fornisce asserzioni per testare i risultati previsti.

Fornisce test runner per l'esecuzione di test.

I test JUnit ti consentono di scrivere codice più velocemente aumentando la qualità

JUnit è elegantemente semplice. È meno complesso e richiede meno tempo.

I test JUnit possono essere eseguiti automaticamente e controllano i propri risultati e forniscono un feedback immediato. Non è necessario esaminare manualmente un report dei risultati del test.

I test JUnit possono essere organizzati in suite di test contenenti casi di test e persino altre suite di test.

Junit mostra l'avanzamento del test in una barra verde se il test sta andando bene e diventa rosso quando un test fallisce.


2

Ho una prospettiva leggermente diversa del motivo per cui è necessaria JUnit.

Puoi effettivamente scrivere tutti i casi di test da solo, ma è ingombrante. Ecco i problemi:

  1. Invece di System.outpossiamo aggiungere if(value1.equals(value2))e restituire 0 o -1 o messaggio di errore. In questo caso, abbiamo bisogno di una classe di test "principale" che esegua tutti questi metodi e controlli i risultati e mantenga quali casi di test falliti e quali sono passati.

  2. Se si desidera aggiungere altri test, è necessario aggiungerli anche a questa classe di test "principale". Modifiche al codice esistente. Se si desidera rilevare automaticamente i casi di test dalle classi di test, è necessario utilizzare la riflessione.

  3. Tutti i test e la classe principale per l'esecuzione dei test non vengono rilevati da eclipse ed è necessario scrivere configurazioni di debug / esecuzione personalizzate per eseguire questi test. Tuttavia, non vedi ancora quelle uscite di colore verde / rosso.

Ecco cosa sta facendo JUnit:

  1. Dispone di assertXXX()metodi utili per stampare utili messaggi di errore dalle condizioni e comunicare i risultati alla classe "principale".

  2. La classe "principale" si chiama runner fornita da JUnit, quindi non è necessario scriverne alcuna. E rileva automaticamente i metodi di prova per riflessione. Se si aggiungono nuovi test con @Testannotazioni, questi vengono automaticamente rilevati.

  3. JUnit ha anche l'integrazione di Eclipse e l'integrazione Maven / Gradle, quindi è facile eseguire test e non dovrai scrivere configurazioni di esecuzione personalizzate.

Non sono un esperto di JUnit, quindi è quello che ho capito fin d'ora, ne aggiungerò altri in futuro.


Immagino che nella prima parte tu abbia scritto cosa avremmo fatto se JUnit non fosse stato lì per rendere l'unità un po 'meglio delle dichiarazioni system.out.println. Forse JUnit è il risultato di tali tentativi da parte di alcuni programmatori e hanno sentito la necessità di scrivere un framework di test separato per eseguire questa automazione, così potrebbe essere nata JUnit.
Saurabh Patil,

1

Non è possibile scrivere alcun caso di test senza utilizzare il framework di test, altrimenti sarà necessario scrivere il frame di test per rendere giustizia ai casi di test. Ecco alcune informazioni su JUnit Framework oltre a ciò che puoi usare TestNG framework.

Che cos'è Junit?

Junit è un framework di test ampiamente utilizzato insieme a Java Programming Language. È possibile utilizzare questo framework di automazione sia per i test unitari che per i test dell'interfaccia utente. Ci aiuta a definire il flusso di esecuzione del nostro codice con diverse annotazioni. Junit si basa sull'idea di "prima test e poi codifica" che ci aiuta ad aumentare la produttività dei casi di test e la stabilità del codice.

Caratteristiche importanti dei test Junit -

  1. È un framework di test open source che consente agli utenti di scrivere ed eseguire casi di test in modo efficace.
  2. Fornisce vari tipi di annotazioni per identificare i metodi di prova.
  3. Fornisce diversi tipi di asserzioni per verificare i risultati dell'esecuzione del test case.
  4. Fornisce inoltre test runner per l'esecuzione efficace dei test.
  5. È molto semplice e quindi fa risparmiare tempo.
  6. Fornisce modi per organizzare i casi di test in forma di semi di prova.
  7. Fornisce risultati di test in modo semplice ed elegante.
  8. È possibile integrare jUnit con Eclipse, Android Studio, Maven & Ant, Gradle e Jenkins

0

JUNIT è il metodo generalmente accettato dallo sviluppatore Java. Laddove possono fornire input previsti simili alla funzione e decidere di conseguenza che il codice scritto è scritto perfettamente o se il test case fallisce, potrebbe essere necessario implementare anche un approccio diverso. JUNIT velocizzerà lo sviluppo e garantirà 0 difetti nella funzione.


0

JUNIT: OSSERVARE E REGOLARE

Ecco la mia prospettiva di JUNIT.

JUNIT può essere usato per,
1) Osservare un comportamento del sistema quando viene aggiunta una nuova unità in quel sistema.
2) Effettuare la regolazione nel sistema per accogliere la "nuova" unità nel sistema.
Che cosa? Esattamente.

Vita reale es.

Quando il tuo parente visita la stanza dell'ostello del college,
1) Farai finta di essere più responsabile.
2) Conserverai tutte le cose dove dovrebbero essere, come le scarpe nello scarpiera non sulla sedia, i vestiti nell'armadio non sulla sedia.
3) Ti libererai di tutto il contrabbando.
4) inizierai cleanUp in ogni dispositivo che possiedi.

In termini di programmazione

Sistema: il tuo codice
UNIT: nuova funzionalità.
Poiché il framework JUNIT viene utilizzato per il linguaggio JAVA, JUNIT = UNITÀ JAVA (può essere).

Supponiamo che tu abbia già un codice ben protetto, ma è arrivato un nuovo requisito e devi aggiungere il nuovo requisito nel tuo codice. Questo nuovo requisito potrebbe violare il codice per alcuni input (testcase).

Un modo semplice per adattare questa modifica è utilizzare il test unitario (JUNIT).
Per questo dovresti scrivere più testcase per il tuo codice quando stai costruendo il tuo codebase. E ogni volta che arriva un nuovo requisito, esegui tutti i casi di test per vedere se un caso di test fallisce. Se No, sei un artista BadA ** e sei pronto per distribuire il nuovo codice.
Se qualcuno dei test ha esito negativo, cambia il codice ed esegui nuovamente test fino a quando non viene visualizzato lo stato verde.

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.