Migrating to JUnit 5

14
Migrating to JUnit 5 (alpha)

Transcript of Migrating to JUnit 5

Page 1: Migrating to JUnit 5

Migrating toJUnit 5 (alpha)

Page 2: Migrating to JUnit 5

JUnit 4 JUnit 5

import org.junit.Test;

public class JUnit4Test { @Test public void aJunit4TestCase() { // write test here } }

import org.junit.gen5.api.Test;

class JUnit5Test { @Test void aJunit5TestCase() { // write test here } }

Page 3: Migrating to JUnit 5

public @interface Test { Class<? extends Throwable> expected() default None.class; long timeout() default 0L; }

JUnit 4 JUnit 5

public @interface Test {

}

public @interface Before {}public @interface After {}

public @interface BeforeEach {}public @interface AfterEach {}

public @interface BeforeClass {}public @interface AfterClass {}

public @interface BeforeAll {}public @interface AfterAll {}

public @interface Ignore { String value() default "";}

public @interface Disabled { String value() default "";}

Page 4: Migrating to JUnit 5

class FunctionalAssertionsWithHamcrest {

@Test void testProcedural() { File file = new File("/some/property.file"); assertTrue(file.exists()); }

@Test void testFunctional() { File file = new File("/some/property.file"); assertTrue(file::exists); }

@Test void testFunctionalGrouped() { File file = new File("/some/property.file"); assertAll(() -> file.canWrite(), () -> file.canRead()); } }

Page 5: Migrating to JUnit 5

class AssumptionsAndExceptions {

@Test void testFullyConditional() { File file = new File("/some/property.file"); assumeTrue(file.exists()); runSomeRoutineDependingOn(file); }

@Test void testPartlyConditional() { File file = new File("/some/property.file"); assumingThat(file.exists()), () -> { runSomeRoutineDependingOn(file); }); }

@Test void testThrowsExcption() { IOException exception = expectThrows(IOException.class, () -> { new File("?").getCanonicalPath(); }); validate(exception); } }

Page 6: Migrating to JUnit 5

JUnit 4 JUnit 5

public class ATest { @Test public void foo() {} }

public class BTest { @Test public void bar() {} }

@RunWith(Suite.class) @Suite.SuiteClasses({ ATest.class, BTest.class}) public class MySuite {}

@Tag(SuiteA.class) public class ATest { @Test public void foo() {} }

@Tags( @Tag(SuiteA.class), @Tag(SuiteB.class) )public class BTest { @Test public void bar() {} }

Page 7: Migrating to JUnit 5

JUnit 4 JUnit 5

public class ATest { @Test public void foo() {} }

public class BTest { @Test public void bar() {} }

@RunWith(Suite.class) @Suite.SuiteClasses({ ATest.class, BTest.class}) public class MySuite {}

@Tag(SuiteA.class) public class ATest { @Test public void foo() {} }

@Tag(SuiteA.class) @Tag(SuiteB.class) @Retention(RUNTIME)public @interface Meta {}

@Metapublic class BTest { @Test public void bar() {} }

Page 8: Migrating to JUnit 5

@DisplayName("A stack") class TestingAStack { Stack<Object> stack = new Stack<Object>();

@Test @DisplayName("is empty") void isEmpty() { Assertions.assertTrue(stack.isEmpty()); }

@Nested @DisplayName("after pushing an element") class AfterPushing {

String anElement = "an element";

@BeforeEach void init() { stack.push(anElement); }

@Test @DisplayName("it is no longer empty") void isEmpty() { Assertions.assertFalse(stack.isEmpty()); } @Test @DisplayName("returns the element when popped") void returnElementWhenPopped() { Assertions.assertEquals(anElement, stack.pop()); } }}

Page 9: Migrating to JUnit 5

class DependencyInjection {

@Test void testSelfAware(TestInfo testInfo) { String name = testInfo.getName(); assertTrue("selfAwareTest", name); }}

public interface TestInfo { String getName(); String getDisplayName(); Set<String> getTags(); }

Page 10: Migrating to JUnit 5

class DependencyInjection {

@Test void testSelfReport(TestReporter testReporter) { long start = System.nanoTime(); doHeavyLifting(); testReporter.publishEntry("time", System.nanoTime() - start); }}

public interface TestReporter { void publishEntry(String key, String value); void publishEntry(Map<String, String> values);}

Page 11: Migrating to JUnit 5

JUnit 4 JUnit 5

public @interface Rule { String value() default "";}public @interface RunWith { Class<? extends Runner> value(); }

public @interface ExtendWith { Class<? extends Extension>[] value(); }

interface ContainerExecutionCondition {...} interface TestExecutionCondition { ... }

interface BeforeAllExtensionPoint { ... } interface BeforeEachExtensionPoint { ... } interface InstancePostProcessor { ... } interface MethodParameterResolver { ... }

interface ExceptionHandlerExtensionPoint { ... } interface AfterEachExtensionPoint { ... } interface AfterAllExtensionPoint { ... }

Page 12: Migrating to JUnit 5

@ExtendWith(FooExtension.class)class FunctionalAssertionsWithHamcrest {

@Test void testProcedural(@Foo File file) { assertTrue(file.exists()); }}

@Retention(RUNTIME) @interface Foo {}

class FooExtension implements MethodParameterResolver {

@Override public boolean supports(Parameter parameter, MethodInvocationContext methodInvocationContext, ExtensionContext extensionContext) { return parameter.isAnnotationPresent(Foo.class); }

@Override public Object resolve(Parameter parameter, MethodInvocationContext methodInvocationContext, ExtensionContext extensionContext){ return new File("some/file"); } }

Page 13: Migrating to JUnit 5

Currently still unsupported:1. Parameterized tests (no test-runner equivalent)2. No test-timeout3. No sorting of test methods

JInit 5 is work-in-progress and the development has sloweddown significantly. Tickets for M1 are up-for-grab on GitHub!

Page 14: Migrating to JUnit 5

http://rafael.codes@rafaelcodes

http://documents4j.comhttps://github.com/documents4j/documents4j

http://bytebuddy.nethttps://github.com/raphw/byte-buddy