JavaRush /Java-Blog /Random-DE /JUnit für JavaRush oder ein wenig über das Testen zu Haus...
Sdu
Level 17

JUnit für JavaRush oder ein wenig über das Testen zu Hause.

Veröffentlicht in der Gruppe Random-DE
Sind Sie es leid, Dutzende Male Testdaten in die Konsole einzugeben, um Ihre Aufgabe zu überprüfen? Willkommen bei der Katze, ich verrate dir, was du damit machen kannst. Das ultimative Ziel dieses Materials besteht darin, den Start der zu lösenden Aufgabe mit verschiedenen Parametern und die Überprüfung der Ergebnisse zu automatisieren, ohne Änderungen am Quellcode vorzunehmen. Wie Sie wahrscheinlich bereits anhand des Titels verstanden haben, wird JUnit unser Hauptassistent in dieser eher einfachen Angelegenheit sein . Wenn Sie noch nichts von Unit-Tests und Unit-Tests gehört haben , empfehle ich Ihnen, eine kleine Pause einzulegen und sich mit diesen Konzepten vertraut zu machen. Glücklicherweise gibt es im Internet genügend Informationen. Nein, du willst nicht? Nun gut, ich denke, das wird kein großes Problem für das Verständnis dessen sein, was passiert. Wissen Sie schließlich, was ein Test und Testen im Allgemeinen ist? Sie tun dies jedes Mal, wenn Sie Ihre Aufgabe starten, geben die Anfangsdaten ein und vergleichen das resultierende Ergebnis mit dem, was Sie erwartet haben.
Hallo, Welt JUnit!
Was ist JUnit? Auf der offiziellen Website des Projekts können wir die folgende Beschreibung lesen:
JUnit ist ein einfaches Framework zum Schreiben wiederholbarer Tests. Es handelt sich um eine Instanz der xUnit-Architektur für Unit-Test-Frameworks.
Für uns bedeutet dies die Möglichkeit, speziell entwickelte Klassen zu schreiben, deren Methoden mit unserem Programm interagieren, das resultierende Ergebnis mit dem Referenzergebnis zu vergleichen und uns zu benachrichtigen, wenn sie nicht übereinstimmen. Um das Prinzip zu verstehen, betrachten Sie ein einfaches Beispiel. Angenommen, wir haben eine Hilfsklasse, von der eine Methode zwei Variablen vom Typ int entgegennimmt und deren Summe zurückgibt: JUnit für JavaRush oder ein wenig über das Testen zu Hause.  - 1 Dies ist die Funktionalität, die wir testen wollen. Glücklicherweise verfügt unsere Lieblingsidee bereits über alles, was Sie zum schnellen Erstellen von Tests benötigen. Wir müssen lediglich den Cursor in die Klassendeklarationszeile setzen, „Alt + Eingabetaste“ drücken und im Kontextmenü „Test erstellen“ auswählen: Anschließend geben Sie an, JUnit für JavaRush oder ein wenig über das Testen zu Hause.  - 2 wo Sie sollten einen Test erstellen. IDEA schlägt vor, eine Testbibliothek (in diesem Material verwende ich JUnit4; damit die Bibliotheksklassen mit dem Projekt verbunden werden können, müssen Sie auf die Schaltfläche „Fixieren“ klicken), die zu testenden Methoden und weitere auszuwählen Optionen. JUnit für JavaRush oder ein wenig über das Testen zu Hause.  - 3 Die IDE erstellt eine Testklassenvorlage: ClassName = TestClassName + „Test“ MethodName = „test“ + TestMethodName JUnit für JavaRush oder ein wenig über das Testen zu Hause.  - 4 Wir müssen nur den Methodenkörper ausfüllen. Dabei helfen die sogenannten „Assertions“ , Methoden von JUnit . Vereinfacht sieht ihre Arbeit so aus: Das erwartete Ergebnis und das Ergebnis des Aufrufs der zu testenden Methode werden an die Methode .assert* übergeben; der Einfachheit halber können Sie als ersten Parameter eine erklärende Nachricht hinzufügen. Sollten die Parameter während des Tests nicht übereinstimmen, werden Sie darüber informiert. Sie können eine Testklasse wie eine normale Klasse zur Ausführung starten. Ich bevorzuge die Tastenkombination Strg+Umschalt+F10 JUnit für JavaRush oder ein wenig über das Testen zu Hause.  - 5
Geben wir die Aufgabe an
Theoretisch ist alles einfach und schön, aber im Kontext des vorgeschlagenen Beispiels ist es nicht wirklich notwendig; wir können dem Computer vertrauen, dass er zwei Zahlen addiert. Uns interessiert mehr, wie es mit echten Problemen weitergeht, die von JavaRush-Studenten gelöst werden; ich schlage zum Beispiel vor, das beliebte Level 05.lesson12.bonus03 zu nehmen.
/* Problem mit Algorithmen Schreiben Sie ein Programm, das: 1. die Zahl N > 0 über die Konsole eingibt 2. dann N Zahlen über die Konsole eingibt 3. das Maximum der eingegebenen N Zahlen anzeigt. */
Wir müssen drei Tests schreiben, für positive, negative Zahlen und eine gemischte Menge.
Je weiter in den Wald...
Hier erwarten uns einige Überraschungen: 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); } }
  • Die Programmlogik ist in der Methode main() untergebracht
  • Die Quelldaten werden nicht an die Methode übergeben, sondern über die Tastatur eingegeben.
  • Die Methode main() gibt das Ergebnis nicht zurück, sondern gibt es auf der Konsole aus.
Wenn der erste Punkt nicht besonders problematisch ist (wir können die Methode main() wie gewohnt aufrufen), dann zwingen uns die nächsten beiden dazu, tiefer in das Thema einzusteigen und unser Gehirn anzustrengen. Ich habe mehrere Lösungen für das Problem gefunden:
  1. Verschieben der Logik zum Finden des Maximums in eine separate Methode.
    • Vorteile: Korrekter Ansatz in Bezug auf Refactoring
    • Nachteile: Das Programm wird mit Code überwuchert, unnötige Strukturen, zumindest wird ein Array oder eine ArrayList hinzugefügt (je nach Geschmack und Farbe...). Es wird nur der Mechanismus zur Ermittlung des Maximums getestet; Dateneingabe und -ausgabe werden nicht überprüft.
  2. Schreiben von Wrappern für System.in/System.out.
    • Vorteile: Wir verwenden keine Bibliotheken von Drittanbietern.
    • Nachteile: Der Weg ist nichts für Anfänger. Die relative Komplexität der Testimplementierung; die Codemenge im Test kann größer sein als in der getesteten Aufgabe.
  3. Verwendung zusätzlicher Bibliotheken für Tests.
    • Vorteile: Sauberer Code in Tests, relativ einfaches Schreiben eines Tests. Der Quellcode der zu testenden Klasse wird nicht geändert.
    • Nachteile: Es müssen Bibliotheken von Drittanbietern mit dem Projekt verbunden werden.
Um ehrlich zu sein, hat mir die dritte Option am besten gefallen, also versuchen wir, sie umzusetzen.
Systemregeln
Eine kurze Suche führte mich auf die Seite http://stefanbirkner.github.io/system-rules/ und es war sofort klar, dass ich das brauchte.
Eine Sammlung von JUnit-Regeln zum Testen von Code, der java.lang.System verwendet.
Laden wir also die Bibliothek herunter . Laden Sie die Commons IO- Bibliothek herunter, die erforderlich ist, damit die Systemregeln funktionieren . Wir verbinden beide Bibliotheken mit unserem Projekt (Datei -> Projektstruktur -> Bibliotheken -> + -> Java) und beginnen mit der Bildhauerei: Nach dem Start fordert Sie unsere Aufgabe auf, N+1 Zahlen über die Konsole einzugeben, wobei die erste Zahl es Ihnen sagt wie viele Zahlen werden ihm folgen. In System Rules wird für diese Zwecke die Klasse TextFromStandardInputStream verwendet. Zunächst müssen wir ein Feld dieses Typs zu unserer Testklasse hinzufügen und es mit der Annotation @Rule markieren: @Rule public final TextFromStandardInputStream systemInMock = emptyStandardInputStream(); Anschließend geben wir direkt in der Testmethode die erforderlichen Daten an: systemInMock.provideText("4\n2\n6\n1\n3\n"); Wie Sie sehen, werden die Zahlen in Textform übertragen und durch die Zeichenfolge „\n“ mit Bindestrich getrennt. Auf dieser Grundlage stellt sich heraus, dass N gleich 4 sein wird, und wir werden das Maximum aus den Zahlen {2, 6, 1, 3} suchen. Als nächstes müssen wir eine Instanz der zu testenden Klasse erstellen und die Methode main() aufrufen. Unser Programm liest die Daten von systemInMock, verarbeitet sie und gibt das Ergebnis aus. Wir müssen es nur noch lesen und mit dem Standard vergleichen. Zu diesem Zweck stellt uns System Rules die Klasse StandardOutputStreamLog zur Verfügung. Wir fügen ein Feld des angegebenen Typs hinzu: @Rule public final StandardOutputStreamLog log = new StandardOutputStreamLog(); Sie können die gedruckten Daten mit der Methode .getLog() lesen. Während Sie das Vorhandensein von Zeilenumbrüchen berücksichtigen müssen, können die endgültigen Optionen wie folgt aussehen: assertEquals("{2, 6, 1, 3}, max = 6", "6", log.getLog().trim()); // oder assertEquals("{2, 6, 1, 3}, max = 6", "6\r\n", log.getLog()); Zwischen Tests, um Vermeiden Sie Datenschichten, Sie müssen das Protokoll löschen. log.clear(); Der vollständige Text meiner Testklasse: 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()); } } Wir starten und genießen. -=!!! WICHTIG!!!=- Dieses Material dient NUR zu Informationszwecken; ich garantiere nicht, dass die Aufgabe auf dem Server erfolgreich getestet wird, wenn das Paket mit der Aufgabe eine fremde Klasse enthält. Bevor Sie eine Aufgabe zur Überprüfung an den Server senden, entfernen Sie alles Überflüssige: unnötige Dateien, unnötige Klassen, auskommentierten Code. Der erfolgreiche Abschluss der von Ihnen erstellten Tests garantiert nicht den erfolgreichen Abschluss der Tests auf dem Server. Ich habe mich bewusst nicht mit dem theoretischen Material befasst: der Theorie des Unit-Tests, JUnit-Annotationen, Assertion usw., das gesamte Material befindet sich in den im Text bereitgestellten Links. Vielleicht haben Sie eigene Möglichkeiten, Aufgaben zu testen, ich bespreche diese gerne in den Kommentaren mit Ihnen.
Kommentare
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION