Neues von JUnit 5.x: From Revolution to Continuous Evolution

Neues von JUnit 5.x: From Revolution to Continuous Evolution

2017 war ein revolutionäres Jahr für das beliebteste Java Testing Framework: Nach zwei Jahren der Entwicklung wurde mit JUnit 5 das erste Major-Release seit mehr als 10 Jahren veröffentlicht. Das JUnit-Team hat danach jedoch keineswegs die Arbeit eingestellt. Im Gegenteil: Seitdem ist die Menge an Feedback und Feature Requests aus der Community merklich gestiegen. Das Resultat sind mittlerweile fünf weitere 5.x Releases, die zusätzliche Features und Verbesserungen beinhalten. Das JUnit-Team arbeitet daran, dieses Tempo beizubehalten und alle paar Monate ein weiteres 5.x Release zu veröffentlichen. Anstatt wie in Version 5.0 komplett neue Packages und Artefakte einzuführen, ist das Ziel die Evolution der bestehenden APIs. Allerdings soll das weitaus häufiger geschehen als in der Vergangenheit.

In diesem Vortrag werden wir uns nach einer kurzen Einführung in JUnit 5 auf die neuen Features der 5.x Releases konzentrieren. Dies sind unter anderem verbesserte Unterstützung für Kotlin, Scannen des Module Path, programmatische Registrierung von Extensions, Tag Expressions, Annotation-basierte bedingte Ausführung von Tests, verbesserte parametrisierte Tests und, zu guter Letzt, parallele Testausführung. Des Weiteren werfen wir eine kurzen Blick auf die meistbenutzten Build Tools für Java (Maven, Gradle, Ant) und deren mittlerweile erstklassige Unterstützung für die neue JUnit Platform. Zum Abschluss diskutieren wir, woran das JUnit-Team aktuell arbeitet und was zukünftige Releases versprechen.

956c7d246841e8507a1e1b96842994db?s=128

Marc Philipp

June 03, 2019
Tweet

Transcript

  1. 5 NEUES VON JUNIT 5 FROM REVOLUTION TO CONTINUOUS EVOLUTION

  2. 5 MARC PHILIPP So ware Engineer bei JUnit Commi er

    seit 2012 Team Lead seit 2016 Twi er: Web: @marcphilipp marcphilipp.de
  3. 5 ✋ SHOW OF HANDS

  4. 5 JUNIT 5 RELEASES 5.0 – 10. September 2017 5.1

    – 18. Februar 2018 5.2 – 29. April 2018 5.3 – 11. September 2018 5.4 – 7. Februar 2019 5.5 – Juni 2019
  5. 5 AGENDA 1. Wie schreibt man Tests und Extensions mit

    JUnit 5? 2. Was ist die JUnit Pla orm und wozu ist sie gut? 3. Was kommt noch und die fängt man mit JUnit 5 an?
  6. 5 JUNIT JUPITER JUNIT JUPITER JUNIT JUPITER JUNIT JUPITER JUNIT

    JUPITER DAS NEUE TESTING FRAMEWORK FÜR JAVA DAS NEUE TESTING FRAMEWORK FÜR JAVA DAS NEUE TESTING FRAMEWORK FÜR JAVA DAS NEUE TESTING FRAMEWORK FÜR JAVA DAS NEUE TESTING FRAMEWORK FÜR JAVA Image: NASA
  7. 5 JUPITER? Nein, “Jupiter” ist einfach ein neuer Name zur

    besseren Unterscheidung der verschiedenen Teile von JUnit 5. … und es ist der fün e Planet von der Sonne aus gezählt. Is wri ng tests rocket science now?
  8. 5 BASICS (DEMO) h ps:/ /github.com/marcphilipp/junit5‑ demo/tree/20190603‑etka

  9. 5 BASICS (RECAP) @Test ist jetzt in org.junit.jupiter.api @Disabled ansta

    @Ignore @BeforeAll , @BeforeEach , @AfterEach , @AfterAll haben neue Namen Assertions sehen ähnlich aus – zusätzlich assertThrows , assertAll Eigene @DisplayNames sta Camel Case @TestInstance(PER_METHOD oder PER_CLASS) @Tag ansta @Category
  10. 5 DISPLAY NAME GENERATORS 5.4 @DisplayNameGeneration(ReplaceUnderscores.class) class A_year_is_not_supported { @Test

    void if_it_is_zero() {/*...*/} @ParameterizedTest @ValueSource(ints = { -1, -4 }) void if_it_is_negative(int year) {/*...*/} }
  11. 5 TEST METHOD ORDERING 5.4 @TestMethodOrder(Random.class) hil sicherzustellen, dass Tests

    nicht Reihenfolge‑abhängig sind @TestMethodOrder(Alphanumeric.class) und @TestMethodOrder(OrderAnnotation.class) für Integra onstests Erweiterbar: MethodOrderer implemen eren
  12. 5 KOTLIN SUPPORT 5.1 import org.junit.jupiter.api.* class KotlinAssertionsDemo { @Test

    fun `expected exception testing`() { val exception = assertThrows<ArithmeticException> { Calculator().divide(1, 0) } assertEquals("/ by zero", exception.message) } @Test fun `grouped assertions`() { assertAll("Person properties", { assertEquals("Jane", person.firstName) }, { assertEquals("Doe", person.lastName) } ) } }
  13. 5 WEITERE TESTARTEN (DEMO) h ps:/ /github.com/marcphilipp/junit5‑ demo/tree/20190603‑etka

  14. 5 WEITERE TESTARTEN (RECAP) @ParameterizedTest mit versch. @Source ‑Annota onen

    @ValueSource , @EnumSource , @CsvSource , @CsvFileSource , @MethodSource , @NullSource 5.4 , @EmptySource 5.4 , @ArgumentsSource(MyProvider.class) , @YourCustomSource @RepeatedTest für “flaky” Tests @TestFactory um dynamisch Tests zu produzieren
  15. 5 PARALLEL EXECUTION 5.3 (DEMO) h ps:/ /github.com/marcphilipp/junit5‑ demo/tree/20190603‑etka

  16. 5 PARALLEL EXECUTION 5.3 (RECAP) Tests laufen standardmäßig sequenziell Parallele

    Ausführung lässt sich per Configura on Parameter ak vieren @Execution(SAME_THREAD oder CONCURRENT) @ResourceLock zur deklara ven Synchronisa on
  17. 5 EXTENSIONS (DEMO) h ps:/ /github.com/marcphilipp/junit5‑ demo/tree/20190603‑etka

  18. 5 EXTENSIONS (RECAP) Registrierung (beliebig viele gleichzei g): Deklara v:

    @ExtendWith an Klassen oder Methoden Programma sch: @RegisterExtension an Feldern 5.1 Global: per ServiceLoader (s. ) Implemen erung: Extension Marker Interface 1 Extension – n Extension Points/Interfaces User Guide
  19. 5 COMPOSED ANNOTATIONS Jupiter‑Annota on können als Meta‑Annota on verwendet

    werden, um eigene Annota onen zu definieren. @Retention(RUNTIME) @Target(METHOD) @ExtendWith(DisabledOnWeekdaysExtension.class) @Tag("example") public @interface DisabledOnWeekdays { DayOfWeek[] value(); }
  20. 5 EXTENSION POINTS Lifecycle: BeforeAllCallback , BeforeEachCallback , BeforeTestExecutionCallback ,

    TestExecutionExceptionHandler , LifecycleMethodExecutionExceptionHandler 5.5 , AfterTestExecutionCallback , AfterEachCallback , AfterAllCallback , InvocationInterceptor 5.5 Andere: ExecutionCondition , ParameterResolver , TestInstanceFactory 5.3 , TestInstancePostProcessor , TestWatcher 5.4 , TestTemplateInvocationContextProvider
  21. 5 TEMPORÄRE VERZEICHNISSE 5.4 import org.junit.jupiter.api.io.TempDir; @Test void writeAndReadFile(@TempDir Path

    tempDir) throws Exception { Path testFile = tempDir.resolve("test.txt"); Files.write(testFile, asList("foo", "bar")); List<String> actualLines = Files.readAllLines(testFile); assertIterableEquals(asList("foo", "bar"), actualLines); }
  22. 5 BEDINGTE AUSFÜHRUNG 5.1 @EnabledOnOs / @DisabledOnOs({LINUX, MAC, …}) @EnabledOnJre

    / @DisabledOnJre({JAVA_11, …}) @Enabled / DisabledIfSystemProperty(named = "someKey", matches = "someValue") @Enabled / DisabledIfEnvironmentVariable(named = "SOME_KEY", matches = "SOME_VALUE")
  23. 5 DEKLARATIVE TIMEOUTS 5.5 @BeforeEach @Timeout(10) void setUp() { //

    schlägt fehl, falls Ausführung länger als 10 Sekunden dauert } @Test @Timeout(value = 500, unit = MILLISECONDS) void someTest() { // schlägt fehl, falls Ausführung länger als 500 Millisekunden dauert }
  24. 5 THIRD‑PARTY EXTENSIONS JUnit Pioneer, Spring, Mockito, Testcontainers, Docker, Wiremock,

    JPA, Selenium/WebDriver, DbUnit, Ka a, Jersey, GreenMail, S3Mock, Citrus Framework, XWiki, … h ps:/ /github.com/junit‑team/junit5/wiki/Third‑party‑ Extensions
  25. 5 AGENDA 1. Wie schreibt man Tests und Extensions mit

    JUnit 5? ✅ 2. Was ist die JUnit Pla orm und wozu ist sie gut? 3. Was kommt noch und die fängt man mit JUnit 5 an?
  26. 5 JUNIT PLATFORM JUNIT PLATFORM JUNIT PLATFORM JUNIT PLATFORM JUNIT

    PLATFORM PLATTFORM ZUM TESTEN AUF DER JVM PLATTFORM ZUM TESTEN AUF DER JVM PLATTFORM ZUM TESTEN AUF DER JVM PLATTFORM ZUM TESTEN AUF DER JVM PLATTFORM ZUM TESTEN AUF DER JVM Image: NASA
  27. 5 JUNIT ALS PLATTFORM? JUnit war schon immer eine Pla

    orm für IDEs und Build Tools für andere Tes ng Frameworks Enge Kopplung (interne APIs, Reflec on, Serializa on)
  28. 5 COUPLING

  29. 5 Wenn JUnit eine Pla orm ist, dann sollten wir

    die Architektur darauf auslegen!
  30. 5 TRENNUNG VON VERANTWORTLICHKEITEN 1. API zum Schreiben von Tests

    und Extensions (Jupiter API) 2. Erweiterbarer Mechanismus zum Auffinden und Ausführen von Tests (Test Engine SPI) 3. API zur Testausführung durch IDEs und Build Tools (Launcher API)
  31. 5 DESIGN‑ZIELE Flexibilität: Neue Features hinzuzufügen ist einfach. Es ist

    klar, ob eine Änderung problema sch ist oder nicht. Rückwärtskompa bilität: JUnit 3/4 Tests laufen immer noch Vorwärtskompa bilität: Alte IDEs und Build Tools können neue Tests ausführen
  32. 5

  33. 5 JUNIT 5 = JUPITER + VINTAGE + PLATFORM

  34. 5 THIRD‑PARTY ENGINES Specsy, Spek, KotlinTest, Cucumber, Drools, jqwik, Brahms,

    Mainrunner, … h ps:/ /github.com/junit‑team/junit5/wiki/Third‑party‑ Extensions
  35. 5 MEHRERE TEST ENGINES (DEMO) h ps:/ /github.com/marcphilipp/junit5‑pla orm‑demo

  36. 5 MEHRERE TEST ENGINES (RECAP) Mehrere Test Engines können in

    einem Testlauf verwendet werden Unterscheidung zwischen Abhängigkeiten in testImplementation und testRuntimeOnly Erlaubt eine schri weise Migra on von einer Test Engine zur anderen (z.B. von Vintage nach Jupiter)
  37. 5 KOMPATIBILITÄT / MIGRATION Vintage Engine führt JUnit 3/4 Tests

    auf der Pla orm aus @Category(UI.class) entspricht com.acme.UI ‑Tag Teilweise Unterstützung von JUnit 4 Rules Unterstützung von @Ignore 5.4 IDEs können Testklassen in die Jupiter API konver eren Migra onswerkzeug aus der Community: h ps:/ /github.com/junit‑pioneer/convert‑junit4‑to‑junit5
  38. 5 BUILD TOOLS Gradle (≥ 4.6), Ant (≥ 1.10.3) und

    Maven Surefire (≥ 2.22.0) unterstützen die JUnit Pla orm Mit dem ConsoleLauncher kann man Tests über die Kommandozeile ausführen und in andere Build Tools (z.B. Bazel) integrieren
  39. 5 IDES Sehr gute Unterstützung IntelliJ IDEA (≥ 2016.2) Eclipse

    (≥ 4.7.1a) Visual Studio Code (Java Test Runner ≥ 0.4.0) Netbeans (≥ 10.0) Für andere IDEs gibt es @RunWith(JUnitPlatform)
  40. 5 TAG EXPRESSIONS 5.1 Erlauben präzise anzugeben, welche Tests basierend

    auf Tags ausgeführt werden sollen: test { useJUnitPlatform { includeTags("(smoke & feature-a) | (!smoke & feature-b)") } }
  41. 5 UNTERSTÜTZUNG FÜR MODULE 5.1 Alle Tests in einem Modul

    ausführen: Den Modulpfad scannen: $ java -jar junit-platform-console-standalone-1.4.0.jar \ --select-module com.acme.foo $ java -jar junit-platform-console-standalone-1.4.0.jar \ --scan-modules
  42. 5 AGENDA 1. Wie schreibt man Tests und Extensions mit

    JUnit 5? ✅ 2. Was ist die JUnit Pla orm und wozu ist sie gut? ✅ 3. Was kommt noch und die fängt man mit JUnit 5 an?
  43. 5 ROADMAP UND ROADMAP UND ROADMAP UND ROADMAP UND ROADMAP

    UND RESSOURCEN RESSOURCEN RESSOURCEN RESSOURCEN RESSOURCEN Image: NASA
  44. 5 ROADMAP Wiederverwendbare Discovery für Test Engines 5.5 M1 Testausführung

    in nutzerdefinierten Threads 5.5 RC1 Deklara ve/globale Timeouts 5.5 RC1 Repor ng‑Format, das neue Features unterstützt (z.B. Tags, Display Names, Report Entries) 5.6 M1 Deklara ve Test Suiten Parametrisierte Testklassen Eure Ideen?
  45. 5 LOSLEGEN? LOSLEGEN! User Guide: Beispielprojekte für Ant, Bazel, Gradle

    und Maven: Javadoc: h p:/ /junit.org/junit5/docs/current/user‑guide/ h ps:/ /github.com/junit‑team/junit5‑samples h p:/ /junit.org/junit5/docs/current/api/
  46. 5 GESUCHT: FEEDBACK! StackOverflow: Code & Issues: Chat mit dem

    Team: Twi er: h p:/ /stackoverflow.com/ques ons/tagged/junit5 h ps:/ /github.com/junit‑team/junit5/ h ps:/ /gi er.im/junit‑team/junit5 h ps:/ /twi er.com/juni eam
  47. 5 UNTERSTÜTZT DAS JUNIT‑TEAM! h ps:/ /junit.org/sponsoring

  48. 5 BEISPIEL‑CODE Jupiter: Pla orm: h ps:/ /github.com/marcphilipp/junit5‑ demo/tree/20190603‑etka h

    ps:/ /github.com/marcphilipp/junit5‑pla orm‑demo
  49. 5 FRAGEN? / auf Twi er @marcphilipp @juni eam

  50. 5 VIELEN DANK!

  51. Bitte geben Sie uns jetzt Ihr Feedback! Neues von JUnit

    5.x: From Revolution to Continuous Evolution Marc Philipp Nächste Vorträge in diesem Raum 11:45 Best Practices für moderne Multicore‑Programmierung, Prof. Dr. Jörg Hettel 13:30 GraphQL als Schnittstelle zum Backend, Christian Kumpe, Thorben Hischke 14:30 Integration ist schwer, Integrationstests umso mehr, Benjamin Muskalla 5