@ 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
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
Java Areas of expertise • Spring * • JUnit 5 • Java EE • Software Architecture • Code Reviews Where you find us • Zurich, Switzerland • @swiftmind • http://www.swiftmind.com
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 …
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
• 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
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
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)
• 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
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
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
discovers and executes tests • for a particular programming model • Automatic registration via Java’s ServiceLoader mechanism • JupiterTestEngine • VintageTestEngine • Implement your own…
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
• 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
• @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
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.
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
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.
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
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
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
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
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
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
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
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))); }
• 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
à 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
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, …