JUnit 5 @ Devoxx BE 2017

JUnit 5 @ Devoxx BE 2017

956c7d246841e8507a1e1b96842994db?s=128

Marc Philipp

November 08, 2017
Tweet

Transcript

  1. 1.

    The New Testing Framework for Java and Testing Platform for

    the JVM @marcphilipp & @sam_brannen JUnit
  2. 2.

    @marcphilipp & @sam_brannen #Devoxx #JUnit5 Marc Philipp •  Software Engineer

    @ LogMeIn in Karlsruhe, Germany •  Consultant, trainer, coach in a former life •  JUnit Maintainer since 2012 •  JUnit’s “Keeper of the Green Bar” for 2016 and 2017 •  Twitter: @marcphilipp •  GitHub: marcphilipp •  Web: marcphilipp.de
  3. 3.

    @marcphilipp & @sam_brannen #Devoxx #JUnit5 > 3000 employees > 18

    offices worldwide SaaS AWS, Azure microservices Spring Boot Docker DevOps
  4. 4.

    @marcphilipp & @sam_brannen #Devoxx #JUnit5 Sam Brannen •  Spring and

    Java Consultant •  Trainer, Coach, … •  Hardcore developer at heart •  Java Developer for about 20 years •  Spring Framework Core Committer since 2007 •  JUnit 5 Core Committer since October 2015
  5. 5.

    @marcphilipp & @sam_brannen #Devoxx #JUnit5 Experts in Spring and Enterprise

    Java Areas of expertise •  Spring * •  JUnit 5 •  Java EE •  Software Architecture •  Code Reviews Where you find us •  Zurich, Switzerland •  @swiftmind •  http://www.swiftmind.com
  6. 6.

    @marcphilipp & @sam_brannen #Devoxx #JUnit5 Agenda •  Impetus for Change

    •  JUnit 5 •  Demos •  Live Coding •  Spring 5 •  Q & A
  7. 9.

    @marcphilipp & @sam_brannen #Devoxx #JUnit5 Impetus for Change •  JUnit

    4.0 was released a decade ago •  a lot has changed since then… •  testing needs have matured •  expectations have grown •  Modularity à big ball of mud (i.e., only THE junit.jar) •  Test discovery and execution à tightly coupled •  Extensibility à lot of room for improvement •  Let’s not forget Java 8 and Java 9 and …
  8. 10.

    @marcphilipp & @sam_brannen #Devoxx #JUnit5 JUnit 4 Runner API • 

    Very powerful •  In fact, it can do anything •  But… you can’t combine Runners •  Parameterized + SpringRunner à no way
  9. 11.

    @marcphilipp & @sam_brannen #Devoxx #JUnit5 JUnit 4… Rules… are meant

    to be broken •  JUnit 4.7: MethodRule à @Rule •  JUnit 4.9: TestRule à @Rule / @ClassRule •  Great for simple use cases •  Can even be combined •  But… a single rule can’t be used for method-level and class-level callbacks •  Plus… zero support for instance-level callbacks •  Case in point: SpringClassRule / SpringMethodRule
  10. 12.

    @marcphilipp & @sam_brannen #Devoxx #JUnit5 JUnit Lambda – Crowdfunding Campaign

    •  Initiated by Johannes Link and Marc Philipp •  Later joined by Matthias Merdes, Stefan Bechtold, & Sam Brannen •  Ran from July to October 2015 •  Raised 53,937 Euros from 474 individuals and companies •  4 companies donated 6 weeks of developer time
  11. 16.

    @marcphilipp & @sam_brannen #Devoxx #JUnit5 Roadmap •  Prototype à December

    2nd, 2015 •  5.0.0-ALPHA à February 1st, 2016 •  Milestones & RCs à July 2016 – August 2017 •  5.0.0 GA à September 10th, 2017 ✅ •  5.0.1 à October 3rd, 2017 ✅ •  5.0.2 & 5.1 M1 à soon
  12. 17.

    @marcphilipp & @sam_brannen #Devoxx #JUnit5 JUnit 5 – in a

    Nutshell •  Modular •  Extensible •  Modern •  Forward and backward compatible •  JUnit Platform supports JUnit 3.8, JUnit 4, and JUnit 5 •  New testing frameworks can be run with JUnit 4 infrastructure o  @RunWith(JUnitPlatform.class)
  13. 18.

    @marcphilipp & @sam_brannen #Devoxx #JUnit5 JUnit 5 – Java Versions

    •  Java 8 •  baseline •  but can be used to test application code compiled against previous JDK versions •  Java 9 •  #WorksFineOnJDK9 •  every artifact has a stable AUTOMATIC-MODULE-NAME •  module-path scanning support coming in 5.1 •  Java 10 •  We just started building against EA builds last week
  14. 19.

    @marcphilipp & @sam_brannen #Devoxx #JUnit5 JUnit 5 = Platform +

    Jupiter + Vintage •  JUnit Platform 1.0.0 •  Foundation for launching testing frameworks on the JVM •  Launcher and TestEngine APIs •  ConsoleLauncher, Gradle plugin, Maven Surefire provider •  JUnit Jupiter 5.0.0 •  New programming model and extension model for JUnit 5 •  JUnit Vintage 4.12.0 •  TestEngine for running JUnit 3 and JUnit 4 based tests Revolutionary Evolutionary Necessary
  15. 20.

    @marcphilipp & @sam_brannen #Devoxx #JUnit5 Launcher API •  Used by

    IDEs and build tools to launch the framework •  Central API for discovering and executing tests via one or more engines •  LauncherDiscoveryRequest •  selectors and filters •  Feedback provided via the TestExecutionListener API •  ConsoleLauncher for command-line support
  16. 21.

    @marcphilipp & @sam_brannen #Devoxx #JUnit5 TestEngine API •  Test engine

    discovers and executes tests •  for a particular programming model •  Automatic registration via Java’s ServiceLoader mechanism •  JupiterTestEngine •  VintageTestEngine •  Implement your own…
  17. 22.

    @marcphilipp & @sam_brannen #Devoxx #JUnit5 Third-party TestEngines •  Specsy • 

    Spek •  Cucumber •  Drools Scenario •  jqwik source: https://github.com/junit-team/junit5/wiki/Third-party-Extensions
  18. 23.

    P L A T F O R M J U

    P I T E R V I N T A G E P A R T Y T H I R D
  19. 24.

    P L A T F O R M J U

    P I T E R V I N T A G E P A R T Y T H I R D
  20. 25.

    @marcphilipp & @sam_brannen #Devoxx #JUnit5 IDEs and Build Tools • 

    IntelliJ: ✅ IDEA 2016.2+ (2017.2.5) •  Eclipse: ✅ Eclipse Oxygen 4.7.1a •  NetBeans: •  Gradle: interim solution from JUnit Team •  to be taken over by Gradle team (end of 2017) •  Android JUnit 5: third-party Android support •  Maven: interim solution from JUnit Team •  being taken over by Maven Surefire team See user guide and sample apps for examples
  21. 27.

    @marcphilipp & @sam_brannen #Devoxx #JUnit5 JUnit Jupiter – Extension Model

    •  Extension •  marker interface •  org.junit.jupiter.api.extension •  package containing all extension APIs •  implement as many as you like •  @ExtendWith(...) •  used to register one or more extensions •  interface, class, or method level o  or as a meta-annotation
  22. 28.

    @marcphilipp & @sam_brannen #Devoxx #JUnit5 Extension APIs •  BeforeAllCallback • 

    BeforeEachCallback •  BeforeTestExecutionCallback •  AfterTestExecutionCallback •  AfterEachCallback •  AfterAllCallback •  TestExecutionExceptionHandler •  ExecutionCondition •  TestInstancePostProcessor •  ParameterResolver •  TestTemplateInvocationContextProvider Lifecycle Callbacks Dependency Injection
  23. 29.

    @marcphilipp & @sam_brannen #Devoxx #JUnit5 JUnit Jupiter – Programming Model

    org.junit.jupiter.api (org.junit.jupiter.params) •  Annotations and meta-annotations •  Assertions and Assumptions •  Custom display names •  Visibility •  Tagging •  Conditional test execution •  Dependency injection for constructors and methods •  Lambda expressions and method references •  Interface default methods •  Nested test classes •  Repeated tests, parameterized tests, dynamic tests
  24. 30.

    @marcphilipp & @sam_brannen #Devoxx #JUnit5 Annotations •  @Test / @TestFactory

    and @Testable for TestEngine implementors •  @RepeatedTest / @ParameterizedTest and @TestTemplate •  @Nested •  @TestInstance •  @BeforeAll / @AfterAll •  @BeforeEach / @AfterEach •  @DisplayName •  @Tag •  @Disabled
  25. 31.

    @marcphilipp & @sam_brannen #Devoxx #JUnit5 JUnit 4 Rule Migration Support

    •  @EnableRuleMigrationSupport o  located in experimental junit-jupiter-migrationsupport module o  registers 3 extensions for JUnit Jupiter •  ExternalResourceSupport o  TemporaryFolder, etc. •  VerifierSupport o  ErrorCollector, etc. •  ExpectedExceptionSupport o  ExpectedException o  minor bugs in 5.0.0; fixed in 5.0.1and 5.0.2
  26. 32.

    @marcphilipp & @sam_brannen #Devoxx #JUnit5 Assertions org.junit.jupiter.api.Assertions •  Limited set

    of core assertions •  assertEquals(), assertNotNull(), etc. •  assertThrows() – λ •  assertTimeout() and assertTimeoutPreemptively() – λ •  assertAll() – λ •  Supplier<String> à λ for lazy failure message evaluation •  message is now the last parameter •  For more power, use AssertJ, Hamcrest, etc.
  27. 33.

    @marcphilipp & @sam_brannen #Devoxx #JUnit5 Assumptions org.junit.jupiter.api.Assumptions •  Limited set

    of core assumptions •  For aborting tests mid-flight •  Otherwise, favor a custom ExecutionCondition for skipping •  assumeTrue() / assumeFalse() •  BooleanSupplier, Supplier<String> – λ •  assumingThat( ? , () -> {} ); – λ
  28. 35.

    @marcphilipp & @sam_brannen #Devoxx #JUnit5 Tagging @Tag("fast") @Test void myFastTest()

    { } •  Declare @Tag on a test interface, class, or method
  29. 36.

    @marcphilipp & @sam_brannen #Devoxx #JUnit5 Custom Tags @Target(METHOD) @Retention(RUNTIME) @Tag("fast")

    public @interface Fast { } •  Declare @Tag as a meta-annotation @Fast @Test void myFastTest() {}
  30. 37.

    @marcphilipp & @sam_brannen #Devoxx #JUnit5 Composed Tags @Target(METHOD) @Retention(RUNTIME) @Tag("fast")

    @Test public @interface FastTest { } •  Declare @Tag as a meta-annotation with other annotations (JUnit, Spring, etc.) @FastTest void myFastTest() { }
  31. 38.

    @marcphilipp & @sam_brannen #Devoxx #JUnit5 Test Names •  Names default

    to test class or test method names •  characters limited based on Java syntax •  Custom display names à @DisplayName •  Can contain spaces, special chars, and even emoji
  32. 39.

    @marcphilipp & @sam_brannen #Devoxx #JUnit5 Dependency Injection •  Extension Model

    meets Programming Model •  ParameterResolver extension API •  resolves parameters for @Test and lifecycle methods o  and even constructors •  can register multiple simultaneously •  only one wins •  Use cases •  server URL, DataSource, Spring ApplicationContext, etc.
  33. 40.

    @marcphilipp & @sam_brannen #Devoxx #JUnit5 TestInfo •  TestInfo: inject into

    constructor, @Test, @BeforeEach, etc. •  access display name, tags, class, method •  TestInfoParameterResolver •  eating our own dog food ;-) •  See also: •  RepetitionInfo for @RepeatedTest •  TestReporter •  MockitoExtension •  SpringExtension
  34. 42.

    @marcphilipp & @sam_brannen #Devoxx #JUnit5 Conditional Test Execution •  Extension

    Model meets Programming Model •  ExecutionCondition •  @Disabled •  DisabledCondition •  eating our own dog food ;-) •  Deactivate via Launcher, system property, or junit-platform.properties file •  junit.conditions.deactivate = org.junit.* Game Changer
  35. 45.

    @marcphilipp & @sam_brannen #Devoxx #JUnit5 Interface Default Methods •  Enables

    the concept of a test interface •  leading to multiple inheritance in tests •  a.k.a., testing traits •  @BeforeAll / @AfterAll •  if using @TestInstance(Lifecyle.PER_CLASS) •  @BeforeEach / @AfterEach •  @Test / @RepeatedTest / @ParameterizedTest / @TestFactory •  @Tag •  @ExtendWith •  See StringTests and TestInterfaceDemo examples in user guide
  36. 47.

    @marcphilipp & @sam_brannen #Devoxx #JUnit5 Nested Test Classes •  Enables

    logical, hierarchical grouping of test classes •  with shared initialization and state from outer classes •  Declare @Nested on non-static nested classes •  i.e., inner classes •  You can even combine nested classes and test interfaces •  See TestingAStack example in user guide and Bowling Game Kata by Tim Riemer
  37. 50.

    @marcphilipp & @sam_brannen #Devoxx #JUnit5 Repeated Tests •  Annotate a

    method with @RepeatedTest instead of @Test o  and specify the number of repetitions •  Optionally have the RepetitionInfo injected as a method parameter •  Optionally override the display name
  38. 51.

    @marcphilipp & @sam_brannen #Devoxx #JUnit5 @RepeatedTest in Action @RepeatedTest(5) void

    repeatedTest(RepetitionInfo repetitionInfo) { assertEquals(5, repetitionInfo.getTotalRepetitions()); } @RepeatedTest( value = 5, name = "Wiederholung {currentRepetition} von {totalRepetitions}” ) void repeatedTestInGerman() { // ... }
  39. 52.

    @marcphilipp & @sam_brannen #Devoxx #JUnit5 Parameterized Tests (junit-jupiter-params) •  Annotate

    a method with @ParameterizedTest instead of @Test o  and specify the source of the arguments o  optionally override the display name •  Sources o  @ValueSource: String, int, long, double o  @EnumSource o  @MethodSource o  @CsvSource & @CsvFileSource o  @ArgumentsSource & custom ArgumentsProvider
  40. 53.

    @marcphilipp & @sam_brannen #Devoxx #JUnit5 Argument Conversion •  Implicit conversion

    o  Primitive types and their wrappers o  Enums o  java.time types (JSR-310) •  Explicit conversion o  @ConvertWith and custom ArgumentConverter o  @JavaTimeConversionPattern built-in support for JSR-310
  41. 54.

    @marcphilipp & @sam_brannen #Devoxx #JUnit5 @ParameterizedTest in Action @ParameterizedTest @ValueSource(strings

    = { "mom", "dad", "radar", "racecar", "able was I ere I saw elba" }) void palindromes(String candidate) { assertTrue(isPalindrome(candidate)); }
  42. 57.

    @marcphilipp & @sam_brannen #Devoxx #JUnit5 Dynamic Tests •  Conventional tests

    are static (i.e., known at compile time) •  @Test •  A DynamicTest is registered at runtime – λ •  as lambda expression in a stream, collection, etc. •  by a method annotated with @TestFactory •  Can also register a DynamicContainer for dynamic nesting •  Somewhat analogous to parameterized tests •  just more… dynamic
  43. 58.

    @marcphilipp & @sam_brannen #Devoxx #JUnit5 Dynamic Tests in Action @TestFactory

    Stream<DynamicTest> dynamicTestsFromIntStream() { // Generates tests for the first 10 even integers. return IntStream.iterate(0, n -> n + 2) .limit(10) .mapToObj(n -> dynamicTest("test" + n, () -> assertTrue(n % 2 == 0))); }
  44. 60.

    @marcphilipp & @sam_brannen #Devoxx #JUnit5 What’s Missing? •  Scenario tests

    •  Ordering •  Parallel execution •  Execution in user-defined thread •  Declarative and programmatic test suites for the JUnit Platform •  Java 9 module-path scanning •  …
  45. 61.
  46. 63.

    @marcphilipp & @sam_brannen #Devoxx #JUnit5 Spring Support for JUnit Jupiter

    •  Fully integrated in Spring Framework 5.0! •  Supports all Core Spring TestContext Framework features •  Constructor and method injection via @Autowired, @Qualifier, @Value •  Conditional test execution via SpEL expressions •  ApplicationContext configuration annotations •  Also works with Spring Framework 4.3 https://github.com/sbrannen/spring-test-junit5
  47. 64.

    @marcphilipp & @sam_brannen #Devoxx #JUnit5 Configuring JUnit Jupiter with Spring

    •  SpringExtension •  @ExtendWith(SpringExtension.class) •  @SpringJUnitConfig •  @ContextConfiguration + SpringExtension •  @SpringJUnitWebConfig •  @SpringJUnitConfig + @WebAppConfiguration •  @EnabledIf / @DisabledIf •  SpEL expression evaluation for conditional execution
  48. 65.
  49. 66.

    @marcphilipp & @sam_brannen #Devoxx #JUnit5 Spring Boot 1.5 + JUnit

    5 – Custom Config @Target(TYPE) @Retention(RUNTIME) @ExtendWith(SpringExtension.class) @SpringBootTest(webEnvironment = MOCK) @AutoConfigureMockMvc @Transactional public @interface SpringEventsWebTest { } •  @SpringBootTest + @AutoConfigureMockMvc + @ExtendWith(SpringExtension.class)
  50. 67.

    @marcphilipp & @sam_brannen #Devoxx #JUnit5 Spring Boot 1.5 + JUnit

    5 – MockMvc Test @SpringEventsWebTest class EventsControllerTests { @Test @DisplayName("Home page should display more than 10 events") void listEvents(@Autowired MockMvc mockMvc) throws Exception { mockMvc.perform(get("/")) .andExpect(view().name("event/list")) .andExpect(model().attribute("events", hasSize(greaterThan(10)))); } } •  @SpringEventsWebTest + method-level DI + MockMvc
  51. 69.

    @marcphilipp & @sam_brannen #Devoxx #JUnit5 JUnit 5 Resources Project Homepage

    à http://junit.org/junit5 User Guide à http://junit.org/junit5/docs/current/user-guide Javadoc à http://junit.org/junit5/docs/current/api GitHub à https://github.com/junit-team Gitter à https://gitter.im/junit-team/junit5 Stack Overflow à http://stackoverflow.com/tags/junit5
  52. 70.

    @marcphilipp & @sam_brannen #Devoxx #JUnit5 Spring Resources Spring Framework à

    http://projects.spring.io/spring-framework Spring Guides à http://spring.io/guides Spring JIRA à https://jira.spring.io Spring on GitHub à https://github.com/spring-projects/spring-framework Stack Overflow à spring, spring-test, spring-mvc, spring-boot, …
  53. 72.

    @marcphilipp & @sam_brannen #Devoxx #JUnit5 JUnit 5 BOF @ Devoxx

    2017 In 20 minutes in BOF room #2 (19:00 – 20:00)