36
JUnit 5

2017-02-20 JUnit 5 - andrena.de 21.02.2017 · • IntelliJ unterstützt JUnit 5 ≥ M2 seit 2016.2 ... • 5.0.0-M5 (Juni 2017): Kompatibilität mit Java 9

  • Upload
    ngohanh

  • View
    225

  • Download
    0

Embed Size (px)

Citation preview

JUnit 5

Marc Philipp• Senior Software Engineer @ Karlsruhe

• JUnit Maintainer seit 2012

• Twitter: @marcphilipp

• Web: http://www.marcphilipp.de

Programmiermodell

DEMO

Meta AnnotationsAnnotationen können miteinander kombiniert werden: @Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)@Tag("fast")@Testpublic @interface FastTest {}

Verwendung: @FastTestvoid test() {}

Entspricht: @Tag("fast")@Testvoid test() {}

@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() {/* ... */}

// ... } } }

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

Warum brauchen wir ein neues JUnit?

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

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)

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

Bisherige ArchitekturJeder verwendet das junit.jar.

Umbenennen einer Instanzvariable ist kein Problem, oder?

4.11 4.12-beta-1

–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.“

Modularisierung

Separation of Concerns1. 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)

P L A T F O R M

J U P I T E RV I N T A G E P A R T YT H I R D

PL

AT

FO

RM

JUP

ITE

R

VIN

TA

GE

PA

RT

YT

HIR

D

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

JUnitPlatform Runner für eine Testklasse

@RunWith(JUnitPlatform.class) public class JupiterTest { @Test void someTest() { // test something } }

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 }

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

Extensions

–JUnit Core Principles

„Prefer extension points over features.“

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!

DEMO

Extension Points• Conditional Test Execution

• ContainerExecutionCondition

• TestExecutionCondition

• General Purpose

• TestInstancePostProcessor

• TestExecutionExceptionHandler

• ParameterResolver

• Test Lifecycle Callbacks

• BeforeAllCallback

• BeforeEachCallback

• BeforeTestExecutionCallback

• AfterTestExecutionCallback

• AfterEachCallback

• AfterAllCallback

Eine Extension — Mehrere Extension Points

• Eine Extension kann mehrere Extension-Interfaces implementieren

• E.g. BeforeEachCallback und AfterEachCallback

ParameterResolver• Konstruktoren und Testmethoden können nun

Parameter haben

• Registrierte ParameterResolvers sind dafür zuständig, die Parameter aufzulösen

• Beispiele: TestInfoParameterResolver, TestReporterParameterResolver, MockitoExtension

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

• upRESThttps://github.com/selesy/uprest

• Declarative Tests für REST APIs

Ausblick

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

M4: @TestTemplateclass 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()); } }

M4: @ParameterizedTestclass 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) { } }

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/

Feedback wanted!

Website: http://junit.org/junit5/

Code & Issues: https://github.com/junit-team/junit5/

Twitter:https://twitter.com/junitteam