JUnit 5: Testing Framework für Java und Plattform für die JVM

JUnit 5: Testing Framework für Java und Plattform für die JVM

956c7d246841e8507a1e1b96842994db?s=128

Marc Philipp

February 20, 2017
Tweet

Transcript

  1. JUnit 5

  2. Marc Philipp • Senior Software Engineer @ Karlsruhe • JUnit

    Maintainer seit 2012 • Twitter: @marcphilipp • Web: http://www.marcphilipp.de
  3. Programmiermodell

  4. DEMO

  5. Meta Annotations Annotationen können miteinander kombiniert werden:
 
 @Target(ElementType.METHOD)
 @Retention(RetentionPolicy.RUNTIME)


    @Tag("fast")
 @Test
 public @interface FastTest {} Verwendung:
 
 @FastTest
 void test() {}
 Entspricht:
 
 @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(11) .mapToObj(n -> dynamicTest("test" + n, () -> { assertTrue(n % 2 == 0); })); }
  8. Warum brauchen wir ein neues JUnit?

  9. Runner • Sehr mächtig: Komplette Ausführung kann angepasst werden •

    Aber: Es kann nur einen Runner pro Testklasse geben! • Runner lassen sich nicht kombinieren, z. B.
 SpringJUnit4ClassRunner + Parameterized
  10. Rules • Neuer Erweiterungsmechanismus seit JUnit 4.7 • Wrapper um

    Ausführung eines Tests (@Rule) oder einer Testklasse (@ClassRule) • Sehr gute Kombinierbarkeit • Aber: Oft nicht mächtig genug, um auf die Testausführung auf unterschiedlichen Ebenen zu beeinflussen (z.B. Spring)
  11. http://blog.takipi.com/the-top-100-java-libraries-in-2016-after-analyzing-47251-dependencies/

  12. Bisherige Architektur Jeder verwendet das junit.jar.

  13. Umbenennen einer Instanzvariable ist kein Problem, oder? 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. Modularisierung

  16. Separation of Concerns 1. Eine API um Tests zu schreiben

    (Jupiter API) 2. Erweiterbarer Mechanismus zum Auffinden und Ausführen von Tests (Test Engine SPI) 3. Eine API für die Testausführung durch 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. Testausführung • IDEs: • IntelliJ unterstützt JUnit 5 ≥ M2

    seit 2016.2 • Eclipse-Unterstützung gibt es auf einem Branch • Übergangslösung für andere IDEs: JUnitPlatform Runner • Gradle/Maven: Plugin/Provider verfügbar • siehe https://github.com/junit-team/junit5-samples • Manuell: ConsoleLauncher
  20. JUnitPlatform Runner für eine Testklasse @RunWith(JUnitPlatform.class) public class JupiterTest {

    @Test void someTest() { // test something } }
  21. JUnitPlatform Runner im Suite-Modus @RunWith(JUnitPlatform.class) @SelectPackages("com.acme") @IncludeEngines({"junit-jupiter", "junit-vintage"}) public class

    JUnit4SuiteDemo { // this class can be run using JUnit 4 }
  22. Kompatibilität • Rückwärtskompatibilität (junit-vintage-engine) ermöglicht schrittweise Migration auf Jupiter •

    Vorwärtskompatibilität (JUnitPlatform Runner) ermöglicht Testausführung mit “alten” Tools
  23. Extensions

  24. –JUnit Core Principles „Prefer extension points over features.“

  25. Registrierung über @ExtendWith • Eine (!) Annotation zur Registrierung von

    Extensions • An Testklassen oder -methoden • Gleichzeitige Registrierung beliebig vieler Extensions wird unterstützt • Kann auch als Meta-Annotation verwendet werden!
  26. DEMO

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

    • General Purpose • TestInstancePostProcessor • TestExecutionExceptionHandler • ParameterResolver • Test Lifecycle Callbacks • BeforeAllCallback • BeforeEachCallback • BeforeTestExecutionCallback • AfterTestExecutionCallback • AfterEachCallback • AfterAllCallback
  28. Eine Extension — Mehrere Extension Points • Eine Extension kann

    mehrere Extension- Interfaces implementieren • E.g. BeforeEachCallback und AfterEachCallback
  29. ParameterResolver • Konstruktoren und Testmethoden können nun Parameter haben •

    Registrierte ParameterResolvers sind dafür zuständig, die Parameter aufzulösen • Beispiele: TestInfoParameterResolver, TestReporterParameterResolver, MockitoExtension
  30. Third-party Extensions (Auswahl) • SpringExtension
 https://github.com/sbrannen/spring-test-junit5 • Core Spring TestContext

    Framework Features • Constructor und Method Injection via @Autowired, @Qualifier, @Value • upREST
 https://github.com/selesy/uprest • Declarative Tests für REST APIs
  31. Ausblick

  32. Roadmap to GA • 5.0.0-M4 (März 2017): Parametrisierte Tests •

    5.0.0-M5 (Juni 2017): Kompatibilität mit Java 9 • 5.0.0-RC1 (Juli 2017): Letzte Änderungen vor GA • 5.0.0 (August 2017): GA
  33. M4: @TestTemplate class MyTest { @TestTemplate @ExtendWith(MyTestTemplateInvocationContextProvider.class) void testTemplate() {

    // test something } } class MyTestTemplateInvocationContextProvider implements TestTemplateInvocationContextProvider { @Override public Iterator<TestTemplateInvocationContext> provide(ContainerExtensionContext context) { return singleton(new MyTestTemplateInvocationContext()).iterator(); } } class MyTestTemplateInvocationContext implements TestTemplateInvocationContext { @Override public String getDisplayName(int invocationIndex) { return "[" + invocationIndex + "]"; } @Override public List<Extension> getAdditionalExtensions() { return asList(new MyParameterResolver(), new MyTestInstancePostProcessor()); } }
  34. M4: @ParameterizedTest class ParameterizedTests { @ParameterizedTest @StringSource({ "foo, 1", "bar,

    2" }) void testWithParametersFromAnnotation(String parameter, int i) { // test something } @ParameterizedTest @MethodSource("providerMethod") void testWithParametersFromMethods(String parameter) { } static Iterable<String> providerMethod() { return asList("foo", "bar"); } @ParameterizedTest @FileSource("foo.csv") @FileSource("bar.csv") void testWithParametersFromFile(String parameter) { } }
  35. Loslegen! User Guide:
 http://junit.org/junit5/docs/current/user-guide/ Beispielprojekte für Gradle and Maven:
 https://github.com/junit-team/junit5-samples

    Javadoc:
 http://junit.org/junit5/docs/current/api/
  36. Feedback wanted! Website:
 http://junit.org/junit5/ Code & Issues:
 https://github.com/junit-team/junit5/ Twitter:
 https://twitter.com/junitteam