Upgrade to Pro — share decks privately, control downloads, hide ads and more …

JUnit 5 wird 5

Marc Philipp
September 27, 2022

JUnit 5 wird 5

Seit dem ersten Release von JUnit 5 im Jahr 2017 sind mittlerweile fast fünf Jahre vergangen. Das JUnit-Team hat danach jedoch keineswegs die Arbeit eingestellt. Im Gegenteil: Seitdem gab es neun weitere Feature- Releases. 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:

- deklarative Test Suites
- JFR Events
- neue Extension Points
- überarbeiteter Support für temporäre Verzeichnisse
- Test Method/Class Execution Order
- ein neues XML Reporting-Format.

Marc Philipp

September 27, 2022
Tweet

More Decks by Marc Philipp

Other Decks in Programming

Transcript

  1. 5
    JUnit 5 wird 5
    JUnit 5 wird 5
    JUnit 5 wird 5
    JUnit 5 wird 5
    JUnit 5 wird 5
    von 5.0 zu 5.9
    von 5.0 zu 5.9
    von 5.0 zu 5.9
    von 5.0 zu 5.9
    von 5.0 zu 5.9

    View full-size slide

  2. 5
    Marc Philipp
    Software Engineer at Gradle
    JUnit committer since 2012
    team lead since 2016
    Twitter:
    Web:
    Email:
    @marcphilipp
    marcphilipp.de
    [email protected]

    View full-size slide

  3. 5
    JUnit 5 is 5!
    🎉
    5.0 – September 10, 2017
    5.1 – February 18, 2018
    5.2 – April 29, 2018
    5.3 – September 11, 2018
    5.4 – February 7, 2019
    5.5 – June 30, 2019
    5.6 – January 7, 2020
    5.7 – September 13, 2020
    5.8 – September 12, 2021
    5.9 – July 26, 2022

    View full-size slide

  4. 5
    Agenda
    1. How to write tests and extensions using JUnit 5?
    2. What is the JUnit Platform and why do we need it?
    3. What’s still to come and how to get started?

    View full-size slide

  5. 5
    JUnit Jupiter
    JUnit Jupiter
    JUnit Jupiter
    JUnit Jupiter
    JUnit Jupiter
    Modern Testing Framework for Java
    Modern Testing Framework for Java
    Modern Testing Framework for Java
    Modern Testing Framework for Java
    Modern Testing Framework for Java
    Image: NASA

    View full-size slide

  6. 5
    P L AT F O R M
    J U P I T E R
    API for writing tests and
    extensions
    Requires Java 8 or later
    Tested with Java, Kotlin, and
    Groovy
    Ships with Java module
    descriptors and OSGi metadata
    JUnit Jupiter

    View full-size slide

  7. 5
    Basics
    @Test
    is now in org.junit.jupiter.api
    Assertions
    instead of Assert
    – a few new ones like
    assertThrows
    , assertAll
    public
    modifier is not required anymore
    import org.junit.jupiter.api.*;
    import static org.junit.jupiter.api.Assertions.*;
    class Tests {
    @Test void test() {
    assertEquals(2, 1 + 1);
    }
    }

    View full-size slide

  8. 5
    Lifecycle Methods
    @BeforeAll
    , @BeforeEach
    , @AfterEach
    , @AfterAll
    have
    new names compared to JUnit 4.x
    class Tests {
    Path resource;
    @BeforeEach void createResource() {
    resource = // ...
    }
    @Test void doSomethingWithResource() {
    assertNotNull(resource); // use resource
    }
    }

    View full-size slide

  9. 5
    More Basics
    @Disabled
    instead of @Ignore
    in JUnit 4.x
    @Tag
    instead of @Category
    in JUnit 4.x
    Custom @DisplayNames
    @DisplayName("Calculator")
    class CalculatorTests {
    @Disabled
    @Tag("feature-addition")
    @DisplayName("should return sum of two numbers when adding")
    void add() {/*...*/}
    }

    View full-size slide

  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) {/*...*/}
    }

    View full-size slide

  11. 5
    Default Display Name Generator
    5.5
    Configurable via a configuration parameter, e.g. in
    src/test/resources/junit-platform.properties
    :
    junit.jupiter.displayname.generator.default = \
    org.junit.jupiter.api.DisplayNameGenerator$ReplaceUnderscores

    View full-size slide

  12. 5
    Nested Tests
    @Nested
    allows using inner classes for grouping and
    sharing setup code.
    @DisplayName("A stack")
    class TestingAStackDemo {
    Stack stack = new Stack<>();
    @Nested
    @DisplayName("when new")
    class WhenNew {
    @DisplayName("is empty")
    void isEmpty() {
    assertTrue(stack.isEmpty());
    }
    // ...
    }
    }

    View full-size slide

  13. 5
    Test Class Order 5.8
    @TestClassOrder
    configures the order of @Nested
    test
    classes
    Extensible: implement ClassOrderer
    Default configurable via
    junit.jupiter.testclass.order.default
    configuration
    parameter
    Also orders test classes within a test run (does not
    work via Maven Surefire).

    View full-size slide

  14. 5
    Test Method Order 5.4
    @TestMethodOrder(Random.class)
    to ensure tests don’t
    rely on any order
    @TestMethodOrder(Alphanumeric.class)
    and
    @TestMethodOrder(OrderAnnotation.class)
    for
    integration tests
    Extensible: implement MethodOrderer
    Default configurable via
    junit.jupiter.testmethod.order.default
    configuration
    parameter 5.7

    View full-size slide

  15. 5
    Parallel Execution 5.3
    Tests are run sequentially by default
    Opt-in and configure parallel execution via
    configuration parameters
    @Execution(SAME_THREAD
    or CONCURRENT)
    Declarative synchronization primitives: @ResourceLock
    and @Isolated 5.7

    View full-size slide

  16. 5
    More ways to test (Demo)
    https://github.com/marcphilipp/junit5-
    demo/tree/20220927-accento-jugka

    View full-size slide

  17. 5
    More ways to test (Recap)
    @ParameterizedTest
    with different @Source
    annotations
    @ValueSource
    , @EnumSource
    , @CsvSource
    ,
    @CsvFileSource
    , @MethodSource
    , @NullSource 5.4 ,
    @EmptySource 5.4 ,
    @ArgumentsSource(MyProvider.class)
    ,
    @YourCustomSource
    @RepeatedTest
    for flaky tests
    @TestFactory
    to produce dynamic tests

    View full-size slide

  18. 5
    Extensions (Demo)
    https://github.com/marcphilipp/junit5-
    demo/tree/20220927-accento-jugka

    View full-size slide

  19. 5
    Extension Registration (Recap)
    Declarative: @ExtendWith
    on classes or methods
    on fields and parameters 5.8
    Programmatic: @RegisterExtension
    on fields 5.1
    Global: Via ServiceLoader
    (opt-in via configuration
    parameter)

    View full-size slide

  20. 5
    Extension Implementation
    (Recap)
    Extension
    marker interface
    one extension – n extension points/interfaces
    package org.junit.jupiter.api.extension;
    /**
    * Marker interface for all extensions.
    * ...
    */
    public interface Extension {}

    View full-size slide

  21. 5
    Extension Points

    View full-size slide

  22. 5
    Support Classes
    Package org.junit.platform.commons.support
    contains:
    AnnotationSupport
    to scan for annotations
    ReflectionSupport
    to scan the class path or look up
    and execute methods etc.

    View full-size slide

  23. 5
    Composed Annotations
    Use Jupiter annotations as meta-annotations to create
    your own annotations.
    @Retention(RUNTIME)
    @Target(METHOD)
    @ExtendWith(DisabledOnWeekdaysExtension.class)
    @Tag("example")
    public @interface DisabledOnWeekdays {
    DayOfWeek[] value();
    }

    View full-size slide

  24. 5
    Built-in Temp Dir Support 5.4
    Supports multiple temp dirs 5.8
    Configurable cleanup-mode 5.9
    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 actualLines = Files.readAllLines(testFile);
    assertIterableEquals(asList("foo", "bar"), actualLines);
    }

    View full-size slide

  25. 5
    Timeouts
    assertTimeout{Preemptively}
    allows writing assertions
    for code blocks within a test
    @Timeout
    is a declarative way to specify timeouts for
    test or lifecycle methods 5.5
    Configurable thread mode 5.9
    junit.jupiter.execution.timeout.{...}.default
    configuration parameters can be used to configure
    defaults 5.5

    View full-size slide

  26. 5
    Built-in Conditions (1/2)
    @Enabled
    /DisabledOnOs({LINUX, MAC, …}) 5.1
    architectures = "aarch64"
    support 5.9
    @Enabled
    /DisabledOnJre({JAVA_11, …}) 5.1
    @Enabled
    /DisabledForJreRange(min = JAVA_9, max =
    JAVA_10) 5.6

    View full-size slide

  27. 5
    Built-in Conditions (2/2)
    @Enabled
    /DisabledIfSystemProperty(named =
    "someKey", matches = "someValue") 5.1
    @Enabled
    /DisabledIfEnvironmentVariable(named =
    "SOME_KEY", matches = "SOME_VALUE") 5.1
    @Enabled
    /DisabledIf("customCondition") 5.7
    @Enabled
    /DisabledInNativeImage 5.9.1

    View full-size slide

  28. 5
    Third-Party Extensions
    JUnit Pioneer, Spring, Mockito, Testcontainers, Docker,
    Wiremock, JPA, Selenium/WebDriver, DbUnit, Kafka,
    Jersey, GreenMail, S3Mock, Citrus Framework, XWiki, …
    https://github.com/junit-team/junit5/wiki/Third-party-
    Extensions

    View full-size slide

  29. 5
    Agenda
    1. How to write tests and extensions using JUnit 5? ✅
    2. What is the JUnit Platform and why do we need it?
    3. What’s still to come and how to get started?

    View full-size slide

  30. 5
    JUnit Platform
    JUnit Platform
    JUnit Platform
    JUnit Platform
    JUnit Platform
    Platform for Testing on the JVM
    Platform for Testing on the JVM
    Platform for Testing on the JVM
    Platform for Testing on the JVM
    Platform for Testing on the JVM
    Image: NASA

    View full-size slide

  31. 5
    Separation of Concerns
    1. An API to write tests and extensions (Jupiter API)
    2. Extensible mechanisms to discover and execute tests
    (Test Engine SPI)
    3. An API for test execution by tools (Launcher API)

    View full-size slide

  32. 5
    JUnit 5
    =
    Jupiter + Vintage + Platform

    View full-size slide

  33. 5
    Third-party Engines
    Spock, TestNG, jqwik, Cucumber, Kotest, Specsy, Spek,
    Drools, ScalaTest, Brahms, Mainrunner, …
    https://github.com/junit-team/junit5/wiki/Third-party-
    Extensions

    View full-size slide

  34. 5
    Mixing Engines
    Multiple test engines can be used in a single test run
    Allows to gradually migrate tests from one test engine
    to another (e.g. from Vintage to Jupiter)
    Demo: on GitHub
    junit5-multiple-engines

    View full-size slide

  35. 5
    Declarative Test Suites 5.8
    Made available via junit-platform-suite-engine
    @Suite
    @SuiteDisplayName("JUnit Platform Suite Demo")
    @SelectPackages("example")
    @IncludeClassNamePatterns(".*Tests")
    class SuiteDemo {
    }

    View full-size slide

  36. 5
    Tag Expressions 5.1
    Precisely specify which tests to run based on tags:
    test {
    useJUnitPlatform {
    includeTags("(smoke & feature-a) | (!smoke & feature-b)")
    }
    }

    View full-size slide

  37. 5
    Test Kit 5.4
    EngineTestKit
    allows testing Extension
    or TestEngine
    implementations.
    EngineExecutionResults results = EngineTestKit
    .engine("junit-jupiter")
    .selectors(selectClass(ExampleTestCase.class))
    .execute();
    results.testEvents()
    .assertThatEvents()
    .haveExactly(1, event(test("skippedTest"),
    skippedWithReason("for demonstration purposes")));
    .haveExactly(1, event(test("failingTest"),
    finishedWithFailure(message("on purpose"))));

    View full-size slide

  38. 5
    New XML reporting format 5.9
    New format
    Enabled via
    junit.platform.reporting.open.xml.enabled=true
    configuration parameter
    Full support for all features of the JUnit Platform such
    as hierarchical test structures, display names, tags, …
    Extensible via additional XML schemas
    Open Test Reporting

    View full-size slide

  39. 5
    Event-based format 5.9
    👍 Suitable for writing and streaming
    👎 Not very human-readable


    View full-size slide

  40. 5
    Hierarchical format 5.9
    Converted from event-based format via CLI tool



    [engine:junit-jupiter]
    JUnit Jupiter
    CONTAINER












    View full-size slide

  41. 5
    Agenda
    1. How to write tests and extensions using JUnit 5? ✅
    2. What is the JUnit Platform and why do we need it? ✅
    3. What’s still to come and how to get started?

    View full-size slide

  42. 5
    Roadmap and
    Roadmap and
    Roadmap and
    Roadmap and
    Roadmap and
    Resources
    Resources
    Resources
    Resources
    Resources
    Image: NASA

    View full-size slide

  43. 5
    On the horizon…
    Additions to the reporting format (screenshots, …)
    Extension APIs for customizing classloaders
    Parameterized test classes
    Built-in support for GraalVM native images
    Your ideas?

    View full-size slide

  44. 5
    Getting Started
    User Guide:
    Sample projects for Ant, Bazel, Gradle, and Maven:
    Javadoc:
    http://junit.org/junit5/docs/current/user-guide/
    https://github.com/junit-team/junit5-samples
    https://junit.org/junit5/docs/current/api/

    View full-size slide

  45. 5
    Today’s Example Code
    https://github.com/marcphilipp/junit5-
    demo/tree/20220927-accento-jugka

    View full-size slide

  46. 5
    More Questions or Feedback?
    Questions: tag on StackOverflow
    Code & Issues: on GitHub
    Chat: on Gitter
    Twitter:
    junit5
    junit-team/junit5
    junit-team/junit5
    @junitteam

    View full-size slide

  47. 5
    Thank you to our sponsors!
    https://junit.org/sponsoring

    View full-size slide

  48. 5
    Thanks!
    👋

    View full-size slide