JUnit 5 - The New Testing Framework for Java and Platform for the JVM

JUnit 5 - The New Testing Framework for Java and Platform for the JVM

Over the last decade a lot has happened in the world of Java and testing, but JUnit 4 hasn't kept up. Now JUnit 5 is here to help shape the future of testing on the JVM with a focus on Java 8 language features, extensibility, and a modern programming API for testing in Java. Moreover, JUnit isn't just a Java testing framework anymore. Third parties are already developing test engines for Scala, Groovy, Kotlin, etc. that run on the new JUnit Platform.

In this session, we will start off with an overview of the inspiration for and architecture of JUnit 5, from launchers to test engines. Then, we will take an example-driven tour of the new Jupiter programming model. We will explore the Jupiter extension model, learn about the extension points it provides, and see how custom extensions for conditional tests, method parameter resolution, lifecycle callbacks etc. are authored and registered. To round off the session, we will discuss migration strategies and compatibility with JUnit 4 and look at the roadmap of what's still to come.

956c7d246841e8507a1e1b96842994db?s=128

Marc Philipp

March 23, 2017
Tweet

Transcript

  1. JUnit 5

  2. Marc Philipp • Senior Software Engineer @ in Germany •

    JUnit Maintainer since 2012 • Twitter: @marcphilipp • Web: http://www.marcphilipp.de
  3. Programming Model

  4. DEMO

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


    @Target(ElementType.METHOD)
 @Retention(RetentionPolicy.RUNTIME)
 @Tag("fast")
 @Test
 public @interface FastTest {} Usage:
 
 @FastTest
 void test() {}
 Equivalent:
 
 @Tag("fast")
 @Test
 void test() {}
  6. @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() {/* ... */} // ... } } }
  7. Dynamic Tests @TestFactory Stream<DynamicTest> dynamicTestsFromStream() { return IntStream.iterate(0, n ->

    n + 2).limit(100) .mapToObj(n -> dynamicTest("test" + n, () -> { assertTrue(n % 2 == 0); })); }
  8. Why do we need a new JUnit?

  9. 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
  10. 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
  11. http://blog.takipi.com/the-top-100-java-libraries-in-2016-after-analyzing-47251-dependencies/

  12. Existing Architecture Everyone uses the junit.jar.

  13. Renaming a private field should not break anything, right? 4.11

    4.12-beta-1
  14. –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.“
  15. Modularization

  16. 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)
  17. 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
  18. 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
  19. JUnitPlatform Runner for a single class import org.junit.jupiter.api.Test; @RunWith(JUnitPlatform.class) public

    class JupiterTest { @Test void someTest() { // test something } }
  20. 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 }
  21. Test Execution • IDEs: • IntelliJ supports JUnit 5 ≥

    M2 since 2016.2 • Eclipse support is available on a branch (see Instructions).
 Official release slated for Oxygen.1. • Interim solution for other IDEs: JUnitPlatform Runner • Gradle/Maven: Plugin/Provider available • see https://github.com/junit-team/junit5-samples • Manually: ConsoleLauncher
  22. Compatibility • Backward compatibility (junit-vintage-engine) enables gradual migration of tests

    to Jupiter API • Forward compatibility (JUnitPlatform Runner) allows test execution with “old” tools
  23. Extensions

  24. Registration via @ExtendWith • Annotate your test classes or methods

    to register extensions • Supports an arbitrary number of extensions at the same time • May be used as a meta-annotation
  25. DEMO

  26. Extension Points • Conditional Test Execution • ContainerExecutionCondition • TestExecutionCondition

    • General Purpose • TestInstancePostProcessor • TestExecutionExceptionHandler • ParameterResolver • Test Lifecycle Callbacks • BeforeAllCallback • BeforeEachCallback • BeforeTestExecutionCallback • AfterTestExecutionCallback • AfterEachCallback • AfterAllCallback
  27. Roadmap

  28. M4: @ParameterizedTest class ParameterizedTests { @ParameterizedTest @CsvSource({ "foo, 1", "bar,

    2" }) void testWithParametersFromAnnotation(String parameter, int i) { // test something } @ParameterizedTest @MethodSource(names = "providerMethod") void testWithParametersFromMethods(String parameter) { } static Iterable<String> providerMethod() { return asList("foo", "bar"); } @ParameterizedTest @CsvFileSource(resources = { "foo.csv", "/bar.csv" }) void testWithParametersFromFile(String parameter) { } }
  29. M4: @RepeatedTest @RepeatedTest(10) void repeatedTest() { // ... }

  30. Roadmap to GA • 5.0.0-M4 (April 2017): Parameterized/RepeatedTests • 5.0.0-M5

    (?) (May 2017): Java 9 compatibility • 5.0.0-RC1 (June 2017): Last fixes before GA • 5.0.0 (July 2017): GA
  31. 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/
  32. Wanted: Feedback! Website:
 http://junit.org/junit5/ Code & Issues:
 https://github.com/junit-team/junit5/ Twitter:
 https://twitter.com/junitteam