81
kgolev.com @kotseto JUnit 5 Kostadin Golev CTO @ Rewards Labs The Next Generation

JUnit 5 - The Next Generation

Embed Size (px)

Citation preview

kgolev.com@kotseto

JUnit 5Kostadin Golev

CTO @ Rewards Labs

The Next Generation

kgolev.com@kotseto

kgolev.com@kotseto

Why JUnit 5? Where Is It? Writing Tests Platform For The JVM Running Along JUnit 3 & 4 Important New Features IDE & Tool Support

kgolev.com@kotseto

kgolev.com@kotseto

Issues with JUnit 4

kgolev.com@kotseto

kgolev.com@kotseto

How bad?Let’s rename some private variables to find out!

kgolev.com@kotseto

kgolev.com@kotseto

4.12-beta-1:

org.junit.ComparisonFailure: expected: null<null> but was: null<null>

4.11:

org.junit.ComparisonFailure: expected:<[1]L> but was:<[2]L>

assertEquals(1, 2)

kgolev.com@kotseto

Extension mechanism

Runner @RunWith(SpringJUnit4ClassRunner.class)

Rule @Rule ExpectedException thrown = none()

kgolev.com@kotseto

Powerful Composable

Runner Rule

kgolev.com@kotseto

Extension mechanism

Powerful Composable?

Runner Rule

kgolev.com@kotseto

kgolev.com@kotseto

Why JUnit 5?

Where Is It? Writing Tests Platform For The JVM Running Along JUnit 3 & 4 Important New Features IDE & Tool Support

kgolev.com@kotseto

Will this work?

kgolev.com@kotseto

There is no single JUnit 5 (JAR)

kgolev.com@kotseto

Not one big fat jarWe have more then ten now, in three groups

kgolev.com@kotseto

JUnit Platform +

JUnit Jupiter +

JUnit Vintage

JUnit 5

kgolev.com@kotseto

JUnit Platform

kgolev.com@kotseto

JUnit Jupiter JUnit Vintage

kgolev.com@kotseto

Why JUnit 5? Where Is It?

Writing Tests Platform For The JVM Running Along JUnit 3 & 4 Important New Features IDE & Tool Support

kgolev.com@kotseto

kgolev.com@kotseto

kgolev.com@kotseto

kgolev.com@kotseto

kgolev.com@kotseto

kgolev.com@kotseto

@Test void exception() { RuntimeException thrown = assertThrows(RuntimeException.class, () -> library.throwRuntimeException("message") );

assertEquals("message", thrown.getMessage()); }

kgolev.com@kotseto

kgolev.com@kotseto

What about Runners and Rules?

kgolev.com@kotseto

We wrote some tests!How do we run them?

kgolev.com@kotseto

Use JUnit 4@RunWith(JUnitPlatform.class) provides limited JUnit 5

functionality

kgolev.com@kotseto

Why JUnit 5? Where Is It? Writing Tests

Platform For The JVM Running Along JUnit 3 & 4 Important New Features IDE & Tool Support

kgolev.com@kotseto

Some HistoryOr how JUnit 5 team discovered they were building a

platform

kgolev.com@kotseto

It started as a big fat jarThen everything got split in small, focused modules

kgolev.com@kotseto

Launcher

<<interface>> Engine

Engine Impl

Jupiter API

implements

JUnit Platform

JUnit Jupiter

kgolev.com@kotseto

Launcher

<<interface>> Engine

JUnit Platform

kgolev.com@kotseto

<<interface>> Engine

Engine Implementation

implements

JUnit Platform

JUnit Jupiter

kgolev.com@kotseto

Jupiter API

JUnit Jupiter

@Test @BeforeEach assertEquals() …

kgolev.com@kotseto

Why JUnit 5? Where Is It? Writing Tests Platform For The JVM

Running Along JUnit 3&4 Important New Features IDE & Tool Support

kgolev.com@kotseto

You can still run your JUnit 3&4 tests

But it will not be JUnit 3&4 running them

kgolev.com@kotseto

Launcher

<<interface>> Engine

Vintage Engine Impl

JUnit 3&4 API

implements

JUnit Platform

JUnit Vintage

kgolev.com@kotseto

JUnit Platform

JUnit Jupiter JUnit Vintage

JUnit5 tests JUnit4 tests

kgolev.com@kotseto

Platform for the JVMDevelopers already started implementing their own

engines, reusing JUnit5 tool integration

kgolev.com@kotseto

Not only for JavaTest Engine implementations exist for

Scala, Kotlin and Groovy

kgolev.com@kotseto

Why JUnit 5? Where Is It? Writing Tests Platform For The JVM Running Along JUnit 3 & 4

Important New Features IDE & Tool Support

kgolev.com@kotseto

assertAll(…)

kgolev.com@kotseto

assertEquals(1, 2); assertEquals("String", "Another String");

org.opentest4j.AssertionFailedError:

Expected :1 Actual :2

kgolev.com@kotseto

assertAll( () -> assertEquals(1, 2), () -> assertEquals("String", “Another String") )

org.opentest4j.MultipleFailuresError: Multiple Failures (2 failures)

expected: <1> but was: <2> expected: <String> but was: <Another String>

kgolev.com@kotseto

What about Runners and Rules (again)?

JUnit5 Extension model

kgolev.com@kotseto

@ExtendWith

kgolev.com@kotseto

kgolev.com@kotseto

Composable & PowerfulUse as many as you want whenever you want them

kgolev.com@kotseto

@ExtendWith(SpringExtension.class) @ExtendWith(MockitoExtension.class) public class SpringTest {

@Autowired SpringComponent component; @Mock Dependency mocked;

kgolev.com@kotseto

class ParameterInTestMethods {

@Test @ExtendWith(MockitoExtension.class) void test(@Mock Dependency mocked) { … }

kgolev.com@kotseto

kgolev.com@kotseto

public class MockitoExtension implements TestInstancePostProcessor {

@Override public void postProcessTestInstance( Object testInstance, ExtensionContext context) { MockitoAnnotations.initMocks(testInstance); } }

kgolev.com@kotseto

Not many extensions yeta few unofficial ones

Spring and Mockito support in next releases

kgolev.com@kotseto

@Nested @DisplayName

kgolev.com@kotseto

public class Library {

private Books books;

public Library(Books books) { this.books = books; }

public void addBook(Book book) { // do something with books

} }

kgolev.com@kotseto

@Test void whenBookExistsThenIncrementAmount() {}

@Test void whenBookExistsThenCheckAmountMoreThenN() {}

@Test void whenBookDoesNotExistThenCreateBook() {}

@Test void whenBookDoesNotExistThenSendNewBookNotification() {}

kgolev.com@kotseto

kgolev.com@kotseto

kgolev.com@kotseto

kgolev.com@kotseto

Tests are often a tree, not a list

kgolev.com@kotseto

kgolev.com@kotseto

@DisplayName("Book is added to library") class BookAddedTest {

@DisplayName("when book exists") @Nested class whenBookExists {

@DisplayName("amount++") @Test void incrementAmount() {}

@DisplayName("check amount > limit") @Test void checkAmountMoreThenLimit() {} }

. . . }

kgolev.com@kotseto

kgolev.com@kotseto

@ParameterizedTest

kgolev.com@kotseto

@Test void strIsLessThenTenChar() { int value = "str".length(); assertTrue(value < 10); }

@Test void StringIsLessThenTenChar() { int value = "String".length(); assertTrue(value < 10); }

kgolev.com@kotseto

kgolev.com@kotseto

kgolev.com@kotseto

kgolev.com@kotseto

@ValueSource(strings = {“str”, “String”}) @ValueSource(ints = {1, 3, 7, 9}) @EnumSource(SomeEnum.class) @CsvSource({"1, 1", "2, 4", "4, 16”}) @CsvFileSource(resources=“testData.csv”)

kgolev.com@kotseto

@MethodSource(names=“stringAndIntProvider")

static Stream<Arguments> stringAndIntProvider() { return Stream.of( ObjectArrayArguments.create("foo", 3), ObjectArrayArguments.create("foobar", 6) ); }

kgolev.com@kotseto

kgolev.com@kotseto

Why JUnit 5? Where Is It? Writing Tests Platform For The JVM Running Along JUnit 3 & 4 Important New Features

IDE & Tool Support

kgolev.com@kotseto

Supports latest release candidate

Support in Oxygen 4.7 BETA Official support target 4.7.1

ETA: September 2017

kgolev.com@kotseto

Surefire provider

Plugin

No native support (yet)

kgolev.com@kotseto

6 September 2017

kgolev.com@kotseto

junit.org/junit5

kgolev.com@kotseto

Questions?@kotseto

kgolev.com/talks/junit5