JavaRush /Java Blog /Random-IT /JUnit per JavaRush o qualcosa sui test a casa.
Sdu
Livello 17

JUnit per JavaRush o qualcosa sui test a casa.

Pubblicato nel gruppo Random-IT
Stanco di digitare i dati dei test nella console decine di volte per controllare la tua attività? Benvenuto al gatto, ti dirò cosa puoi farci. L'obiettivo finale di questo materiale sarà automatizzare l'avvio dell'attività da risolvere con vari parametri e controllare i risultati senza apportare modifiche al codice sorgente. Come probabilmente hai già capito dal titolo, il nostro assistente principale in questa faccenda piuttosto semplice sarà JUnit . Se non hai ancora sentito parlare di unit test e unit test , ti consiglio di prenderti una piccola pausa e familiarizzare con questi concetti, fortunatamente su Internet si trovano abbastanza informazioni. No, non vuoi? Bene, ok, penso che questo non diventerà un grosso problema per capire cosa sta succedendo. Dopotutto, sai cosa sono un test e i test in generale? Lo fai ogni volta che avvii la tua attività, inserisci i dati iniziali e confronta il risultato risultante con quello che ti aspettavi di vedere.
Ciao, mondo JUnit!
Cos'è JUnit? Sul sito ufficiale del progetto possiamo leggere la seguente descrizione:
JUnit è un framework semplice per scrivere test ripetibili. È un'istanza dell'architettura xUnit per i framework di unit test.
Per noi questo significa la possibilità di scrivere classi appositamente progettate i cui metodi interagiranno con il nostro programma, confronteranno il risultato risultante con quello di riferimento e ci informeranno se non corrispondono. Per comprendere il principio, consideriamo un semplice esempio. Supponiamo di avere una classe ausiliaria, uno dei cui metodi prende due variabili di tipo int e restituisce la loro somma: JUnit per JavaRush o qualcosa sui test a casa.  -1 questa è la funzionalità che proveremo a testare. Fortunatamente la nostra IDEA preferita ha già tutto il necessario per creare velocemente dei test, tutto quello che ci serve è posizionare il cursore nella riga di dichiarazione della classe, premere "Alt + Invio" e selezionare "Crea Test" nel menu contestuale: Dopo aver JUnit per JavaRush o qualcosa sui test a casa.  - 2 specificato dove dovresti creare un test, IDEA suggerisce di scegliere una libreria di testing (in questo materiale utilizzo JUnit4; per poter collegare le classi della libreria al progetto, è necessario fare clic sul pulsante “Fix”), metodi da testare e ulteriori opzioni. JUnit per JavaRush o qualcosa sui test a casa.  - 3 L'IDE creerà un modello di classe di test: ClassName = TestClassName + "Test" MethodName = "test" + TestMethodName JUnit per JavaRush o qualcosa sui test a casa.  - 4 Dobbiamo solo compilare il corpo del metodo. Le cosiddette “Asserzioni” , metodi forniti da JUnit , aiuteranno in questo . In modo semplificato, il loro lavoro è simile a questo: il risultato atteso e il risultato della chiamata al metodo in prova vengono passati al metodo .assert*; per comodità è possibile aggiungere un messaggio esplicativo come primo parametro. Se i parametri non corrispondono durante il test, verrai informato. Puoi avviare una classe di test per l'esecuzione proprio come una classe normale, preferisco usare la combinazione di tasti Ctrl+Shift+F10 JUnit per JavaRush o qualcosa sui test a casa.  - 5
Specifichiamo l'attività
In teoria tutto è semplice e bello, ma nel contesto dell’esempio proposto non è proprio necessario; possiamo fidarci del computer per sommare due numeri. A noi interessa di più come andranno le cose con i problemi reali risolti dagli studenti JavaRush; ad esempio, suggerisco di frequentare l'amato livello05.lesson12.bonus03.
/* Problema sugli algoritmi Scrivere un programma che: 1. inserisce il numero N > 0 dalla console 2. quindi inserisce N numeri dalla console 3. visualizza il massimo degli N numeri inseriti. */
Dobbiamo scrivere tre test, per numeri positivi, negativi e un insieme misto.
Più ci si addentra nella foresta...
È qui che ci aspettano alcune sorprese: public class UtilApp { public static void main(String[] args) throws Exception { BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); //напишите здесь ваш code int n; int maximum; /* Конечно же я не буду размещать решение задачи ;) Код приведенный тут переработан для наглядности, и не в коем случае не означает что он должен присутствовать в "правильном решении" */ System.out.println(maximum); } }
  • La logica del programma è inserita nel metodo main()
  • I dati di origine non vengono passati al metodo, ma vengono immessi dalla tastiera.
  • Il metodo main() non restituisce il risultato, ma lo invia alla console.
Se il primo punto non è particolarmente problematico (possiamo chiamare come al solito il metodo main()), i successivi due ci costringono ad approfondire l'argomento e a sforzare il nostro cervello. Ho trovato diverse soluzioni al problema:
  1. Spostare la logica per trovare il massimo in un metodo separato.
    • Pro: approccio corretto in termini di refactoring
    • Contro: Il programma si riempie di codice, strutture non necessarie, viene aggiunto almeno un array o ArrayList (a seconda del gusto e del colore...). Viene testato solo il meccanismo per trovare il massimo; l'input e l'output dei dati non vengono controllati.
  2. Scrittura di wrapper per System.in/System.out.
    • Pro: Non utilizziamo librerie di terze parti.
    • Contro: Il percorso non è per principianti. La complessità relativa dell'implementazione del test; la quantità di codice nel test potrebbe essere maggiore rispetto all'attività da testare.
  3. Utilizzo di librerie aggiuntive per i test.
    • Pro: codice pulito nei test, relativa facilità di scrivere un test. Il codice sorgente della classe in prova non viene modificato.
    • Contro: Necessità di collegare librerie di terze parti al progetto.
Ad essere sincero, mi è piaciuta di più la terza opzione, quindi proviamo a implementarla.
Regole di sistema
Una breve ricerca mi ha portato alla pagina http://stefanbirkner.github.io/system-rules/ ed è diventato subito chiaro che questo era ciò di cui avevo bisogno.
Una raccolta di regole JUnit per testare il codice che utilizza java.lang.System.
Quindi scarichiamo la libreria . Scarica la libreria Commons IO necessaria per il funzionamento delle regole di sistema . Colleghiamo entrambe le librerie al nostro progetto (File -> Struttura del progetto -> Librerie -> + -> Java) e iniziamo a scolpire: dopo il lancio, la nostra attività ti chiede di inserire N+1 numeri dalla console, dove il primo numero ti dice quanti numeri lo seguiranno. In System Rules viene utilizzata per questi scopi la classe TextFromStandardInputStream: inizialmente dobbiamo aggiungere un campo di questo tipo alla nostra classe di test e contrassegnarlo con l'annotazione @Rule: @Rule public final TextFromStandardInputStream systemInMock = emptyStandardInputStream(); poi, direttamente nel metodo di test indichiamo i dati necessari: systemInMock.provideText("4\n2\n6\n1\n3\n"); Come puoi vedere, i numeri vengono trasmessi in forma di testo e sono separati da una stringa di trattini "\n". Sulla base di ciò, risulta che N sarà uguale a 4 e cercheremo il massimo tra i numeri {2, 6, 1, 3}. Successivamente, dobbiamo creare un'istanza della classe da testare e chiamare il metodo main(). Il nostro programma legge i dati da systemInMock, li elabora e stampa il risultato, a noi non resta che leggerli e confrontarli con lo standard. Per fare ciò, le regole di sistema ci mettono a disposizione la classe StandardOutputStreamLog. Aggiungiamo un campo del tipo specificato: @Rule public final StandardOutputStreamLog log = new StandardOutputStreamLog(); Puoi leggere i dati stampati utilizzando il metodo .getLog(), mentre devi tenere conto della presenza di caratteri di fine riga, le opzioni finali possono essere così: assertEquals("{2, 6, 1, 3}, max = 6", "6", log.getLog().trim()); // or assertEquals("{2, 6, 1, 3}, max = 6", "6\r\n", log.getLog()); Tra i test, per evita la stratificazione dei dati, devi cancellare il registro log.clear(); Il testo completo della mia lezione di prova: import org.junit.Rule; import org.junit.Test; import org.junit.contrib.java.lang.system.StandardOutputStreamLog; import org.junit.contrib.java.lang.system.TextFromStandardInputStream; import static org.junit.Assert.*; import static org.junit.contrib.java.lang.system.TextFromStandardInputStream.emptyStandardInputStream; public class UtilAppTest { @Rule public final TextFromStandardInputStream systemInMock = emptyStandardInputStream(); @Rule public final StandardOutputStreamLog log = new StandardOutputStreamLog(); @Test public void testAddition() throws Exception { systemInMock.provideText("4\n2\n6\n1\n3\n"); UtilApp utilApp = new UtilApp(); utilApp.main(new String[]{}); assertEquals("{2, 6, 1, 3}, max = 6", "6", log.getLog().trim()); systemInMock.provideText("5\n-100\n-6\n-15\n-183\n-1\n"); log.clear(); utilApp.main(new String[]{}); assertEquals("{-100, -6, -15, -183, -1}, max = -1", "-1", log.getLog().trim()); systemInMock.provideText("3\n2\n0\n-1\n"); log.clear(); utilApp.main(new String[]{}); assertEquals("{2, 0, -1}, max = 2", "2", log.getLog().trim()); } } Lanciamo e divertiamoci. -=!!! IMPORTANTE!!!=- Questo materiale viene fornito SOLO a scopo informativo; non garantisco il successo del test dell'attività sul server se è presente una classe estranea nel pacchetto con l'attività. Prima di inviare un'attività di verifica al server, rimuovi tutto ciò che è estraneo: file non necessari, classi non necessarie, codice commentato. Il completamento con successo dei test creati non garantisce il completamento con successo dei test sul server. Non ho masticato deliberatamente il materiale teorico: la teoria dei test unitari, le annotazioni JUnit, l'asserzione, ecc., tutto il materiale è nei collegamenti forniti nel testo. Forse hai i tuoi modi di testare le attività, sarò felice di discuterne con te nei commenti.
Commenti
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION