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

JUnit 5 @ Solutions HH

Marc Philipp
September 06, 2017

JUnit 5 @ Solutions HH

Marc Philipp

September 06, 2017
Tweet

More Decks by Marc Philipp

Other Decks in Programming

Transcript

  1. JUnit 5

    View Slide

  2. Christian Stein
    • Software developer @ MICROMATA Kassel/Bonn
    • JUnit 5 core team member since 2017
    • Github: https://github.com/sormuras
    • Twitter: @sormuras

    View Slide

  3. Marc Philipp
    • Staff Software Engineer @ in Karlsruhe
    • JUnit Maintainer since 2012
    • Twitter: @marcphilipp
    • Web: http://www.marcphilipp.de

    View Slide

  4. Programming Model

    View Slide

  5. DEMO
    https://github.com/marcphilipp/junit5-demo/tree/20170906-solutions.hamburg

    View Slide

  6. Meta Annotations
    Annotations can be combined to enable re-use:


    @Target(ElementType.METHOD)

    @Retention(RetentionPolicy.RUNTIME)

    @Tag("integration")

    @Test

    public @interface IntegrationTest {}
    Usage:


    @IntegrationTest

    void test() {}

    Equivalent:


    @Tag("integration")

    @Test

    void test() {}

    View Slide

  7. @ParameterizedTest Sources
    • @ValueSource(ints = { 1, 2, 3 })
    • @EnumSource(TimeUnit.class)
    • @MethodSource(names = "myProviderMethod")
    • @CsvSource({ "foo, 1", "bar, 2", "'baz, qux', 3" })
    • @CsvFileSource(resources = "/two-column.csv")
    • @ArgumentsSource(MyArgumentsProvider.class)
    • @YourCustomSource

    View Slide

  8. @Nested Tests
    @DisplayName("A stack")
    class TestingAStackDemo {
    @Test
    @DisplayName("is instantiated with new Stack()")
    void isInstantiatedWithNew() {/* ... */}
    @Nested
    @DisplayName("when new")
    class WhenNew {
    @BeforeEach
    void createNewStack() {/* ... */}
    @Test
    @DisplayName("is empty")
    void isEmpty() {/* ... */}
    // ...
    @Nested
    @DisplayName("after pushing an element")
    class AfterPushing {
    @BeforeEach
    void pushAnElement() {/* ... */}
    @Test
    @DisplayName("it is no longer empty")
    void isNotEmpty() {/* ... */}
    // ...
    }
    }
    }

    View Slide

  9. Dynamic Tests
    @TestFactory
    Stream dynamicTestsFromStream() {
    return IntStream.iterate(0, n -> n + 2).limit(100)
    .mapToObj(n -> dynamicTest("test" + n, () -> {
    assertTrue(n % 2 == 0);
    }));
    }

    View Slide

  10. @RepeatedTest
    @RepeatedTest(10)
    void repeatedTest() {
    // ...
    }

    View Slide

  11. Why do we need a new
    JUnit?

    View Slide

  12. Runner
    • Very powerful: Almost every aspect of test
    execution can be changed
    • But: You can only have one Runner per test class!
    • You can’t combine Runners, e.g.

    SpringJUnit4ClassRunner + Parameterized

    View Slide

  13. Rules
    • Extension mechanism introduced in JUnit 4.7
    • Wraps execution of a test (@Rule) or a test class
    (@ClassRule)
    • Designed to be combined — great for simple use cases
    • But: a single rule cannot be used for method-level and
    class-level callbacks, no support for instance-level callbacks

    View Slide

  14. http://blog.takipi.com/the-top-100-java-libraries-in-2016-after-analyzing-47251-dependencies/

    View Slide

  15. Existing Architecture
    Everyone uses the junit.jar.

    View Slide

  16. Renaming a private field should
    not break anything, right?
    4.11 4.12-beta-1

    View Slide

  17. –Johannes Link, https://jaxenter.com/crowdfunding-for-junit-lambda-is-
    underway-119546.html
    „The success of JUnit as a platform prevents the
    development of JUnit as a tool.“

    View Slide

  18. Design Goals for JUnit 5
    • Modern programming model for writing tests (Java 8!)
    • Powerful extension model with a focus on composability
    • API Segregation: Decouple test execution/reporting from test
    definition
    • Compatibility with older releases + migration path
    • Modularization + no external dependencies

    View Slide

  19. Modularization

    View Slide

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

    View Slide

  21. P L AT F O R M
    J U P I T E R
    V I N TA G E
    P A R T Y
    T H I R D

    View Slide

  22. P L AT F O R M
    J U P I T E R
    V I N TA G E
    P A R T Y
    T H I R D

    View Slide

  23. JUnitPlatform Runner for a single class
    import org.junit.jupiter.api.Test;
    @RunWith(JUnitPlatform.class)
    public class JupiterTest {
    @Test
    void someTest() {
    // test something
    }
    }

    View Slide

  24. JUnitPlatform Runner in suite mode
    @RunWith(JUnitPlatform.class)
    @SelectPackages("com.acme")
    @IncludeEngines({"junit-jupiter", "junit-vintage"})
    public class JUnit4SuiteDemo {
    // this class can be run using JUnit 4
    }

    View Slide

  25. IDE Support
    • IntelliJ supports JUnit 5 ≥ M2 since 2016.2
    • Eclipse support is available on Eclipse Marketplace:

    https://marketplace.eclipse.org/content/junit-5-support-
    beta-oxygen

    Will be integrated without requiring any additional work
    in Oxygen.1a
    • Interim solution for other IDEs: JUnitPlatform Runner

    View Slide

  26. Build Tool Support
    • Gradle/Maven: Plugin/Provider available
    • see https://github.com/junit-team/junit5-
    samples
    • Manually: ConsoleLauncher

    View Slide

  27. Compatibility
    • Backward compatibility
    (junit-vintage-engine)
    enables gradual migration
    of tests to Jupiter API
    • Forward compatibility
    (JUnitPlatform Runner)
    allows test execution with
    “old” tools

    View Slide

  28. Extensions

    View Slide

  29. Extension Registration
    • Declarative: Annotate your test classes or methods with
    @ExtendWith to register extensions
    • Supports an arbitrary number of extensions at the
    same time
    • May be used as a meta-annotation
    • Global: Opt-in support for registration via ServiceLoader

    View Slide

  30. DEMO
    https://github.com/marcphilipp/junit5-demo/tree/20170906-solutions.hamburg

    View Slide

  31. Extension Points
    • Conditional Test Execution
    • ExecutionCondition
    • General Purpose
    • TestInstancePostProcessor
    • ParameterResolver
    • TestTemplateInvocationContext-
    Provider
    • Test Lifecycle Callbacks
    • BeforeAllCallback
    • BeforeEachCallback
    • BeforeTestExecutionCallback
    • TestExecutionExceptionHandler
    • AfterTestExecutionCallback
    • AfterEachCallback
    • AfterAllCallback

    View Slide

  32. Roadmap
    • 5.0 M4 (April 2017): parameterized and repeated tests ✔
    • 5.0 M5 (June 2017): dynamic containers, test instance lifecycle management, and
    minor API changes ✔
    • 5.0 M6 (July 2017): Java 9 compatibility, validation (e.g. tag syntax), and bug fixes ✔
    • 5.0 RC1, RC2, RC3 (July/August 2017): bug fixes and documentation improvements
    before GA. ✔
    • 5.0 GA (this week, really!): First general availability release
    • 5.1 (October?): additional features

    View Slide

  33. Summary

    View Slide

  34. What’s in it for me?
    • Modern programming model
    • Powerful extension points
    • Gentle migration path
    • Good tool support
    • Flexible platform/plugin architecture

    View Slide

  35. Getting Started
    User Guide:

    http://junit.org/junit5/docs/current/user-guide/
    Sample projects for Gradle and Maven:

    https://github.com/junit-team/junit5-samples
    Javadoc:

    http://junit.org/junit5/docs/current/api/

    View Slide

  36. Wanted: Feedback!
    Website:

    http://junit.org/junit5/
    Code & Issues:

    https://github.com/junit-team/junit5/
    Twitter:

    https://twitter.com/junitteam

    View Slide