junit 5 - the next generation of junit - ted's tool time

16
Ted’s Tool Time Ted Vinke First8 JUnit 5 - Next Gen JUnit May 2016

Upload: ted-vinke

Post on 12-Apr-2017

270 views

Category:

Technology


1 download

TRANSCRIPT

Page 1: JUnit 5 - The Next Generation of JUnit - Ted's Tool Time

Ted’s Tool TimeTed VinkeFirst8

JUnit 5 - Next Gen JUnit

May 2016

Page 2: JUnit 5 - The Next Generation of JUnit - Ted's Tool Time
Page 3: JUnit 5 - The Next Generation of JUnit - Ted's Tool Time

Writing Tests

Dependencies

● Group ID: org.junit

● Version: 5.0.0-SNAPSHOT

● Artifact IDs:

○ junit-commons

○ junit-console

○ junit-engine-api

○ junit-gradle

○ junit-launcher

○ junit4-engine

○ junit4-runner

○ junit5-api

○ junit5-engine

○ surefire-junit5

import static org.junit.gen5.api.Assertions.assertEquals;

import org.junit.gen5.api.Test;

class FirstJUnit5Tests {

@Test void myFirstTest() { assertEquals(2, 1 + 1); }

} No need to be public anymore - package ok, private not

The API to write tests is in junit-api

Own Junit 5 @Test annotation - with no timeout, expected, etc

No deps on JUnit 4 - new namespace

org.junit.gen5

Page 4: JUnit 5 - The Next Generation of JUnit - Ted's Tool Time

class Lifecycle {

@BeforeAllstatic void initializeExternalResources() {

System.out.println("Initializing external resources...");

}

@BeforeEachvoid initializeMockObjects() {

System.out.println("Initializing mock objects...");

}

@Testvoid someTest() {

System.out.println("Running some test...");assertTrue(true);

}

@Testvoid otherTest() {

...

Lifecycle (1)

Basics are very similar to JUnit 4.

Source: http://blog.codefx.org/libraries/junit-5-basics/

As with JUnit4 - new instance created for every test method

Page 5: JUnit 5 - The Next Generation of JUnit - Ted's Tool Time

@Testvoid otherTest() {

assumeTrue(true);System.out.println("Running another test...");assertNotEquals(1, 42, "Why wouldn't these be the

same?");}

@Test@Disabledvoid disabledTest() {

System.exit(1);}

@AfterEachvoid tearDown() {

System.out.println("Tearing down...");}

@AfterAllstatic void freeExternalResources() {

System.out.println("Freeing external resources...");

} }

Lifecycle (2)

Basics are very similar to JUnit 4.

Prefer @Disabled(“for reason X”)

Page 6: JUnit 5 - The Next Generation of JUnit - Ted's Tool Time

JUnit 5 comes with many of the assertion methods that JUnit 4 has and adds a few that lend themselves well to being used with Java 8 lambdas.

All JUnit 5 assertions are static methods in the org.junit.gen5.Assertions class.

import static org.junit.gen5.api.Assertions.*;

import org.junit.gen5.api.Test;

class AssertionsDemo {

@Test void standardAssertions() { assertEquals(2, 2); assertEquals(4, 4, "The optional assertion message is now the last parameter."); assertTrue(2 == 2, () -> "Assertion messages can be lazily evaluated -- " + "to avoid constructing complex messages unnecessarily."); }}

Assertions

Page 7: JUnit 5 - The Next Generation of JUnit - Ted's Tool Time

JUnit 5 comes with many of the assertion methods that JUnit 4 has and adds a few that lend themselves well to being used with Java 8 lambdas.

All JUnit 5 assertions are static methods in the org.junit.gen5.Assertions class.

import static org.junit.gen5.api.Assertions.*;

import org.junit.gen5.api.Test;

class AssertionsDemo {

@Test void standardAssertions() { assertEquals(2, 2); assertEquals(4, 4, "The optional assertion message is now the last parameter."); assertTrue(2 == 2, () -> "Assertion messages can be lazily evaluated -- " + "to avoid constructing complex messages unnecessarily."); }}

Assertions import static org.junit.gen5.api.Assertions.*;

import org.junit.gen5.api.Test;

class AssertionsDemo {

@Test void groupedAssertions() { assertAll("address", () -> assertEquals("John", address.getFirstName()), () -> assertEquals("User", address.getLastName()) ); }

}

In a grouped assertion all assertions are executed, and and

failures will be reported together.

org.opentest4j.MultipleFailuresError: address (2 failures)expected: <John> but was: <Ted>expected: <User> but was: <Vinke>

Hey, what’s this “opentest4j”? That’s

the Open Test Alliance for the JVM

Page 8: JUnit 5 - The Next Generation of JUnit - Ted's Tool Time

JUnit 5 comes with many of the assertion methods that JUnit 4 has and adds a few that lend themselves well to being used with Java 8 lambdas.

All JUnit 5 assertions are static methods in the org.junit.gen5.Assertions class.

import static org.junit.gen5.api.Assertions.*;

import org.junit.gen5.api.Test;

class AssertionsDemo {

@Test void standardAssertions() { assertEquals(2, 2); assertEquals(4, 4, "The optional assertion message is now the last parameter."); assertTrue(2 == 2, () -> "Assertion messages can be lazily evaluated -- " + "to avoid constructing complex messages unnecessarily."); }}

Assertions import static org.junit.gen5.api.Assertions.*;

import org.junit.gen5.api.Test;

class AssertionsDemo {

@Test void groupedAssertions() { // In a grouped assertion all assertions are executed, and any // failures will be reported together. assertAll("address", () -> assertEquals("John", address.getFirstName()), () -> assertEquals("User", address.getLastName()) ); }

}

import static org.junit.gen5.api.Assertions.*;

import org.junit.gen5.api.Test;

class AssertionsDemo {

@Test void exceptionTesting() { Throwable exception = expectThrows(IllegalArgumentException.class, () -> { throw new IllegalArgumentException("a message"); }); assertEquals("a message", exception.getMessage()); }

}

expectedThrows replaces expected and ExpectedException

Page 9: JUnit 5 - The Next Generation of JUnit - Ted's Tool Time

import static org.junit.gen5.api.Assertions.assertEquals;import static org.junit.gen5.api.Assumptions.*;import org.junit.gen5.api.Test;

public class AssumptionsDemo {

@Test void testOnlyOnCiServer() { assumeTrue("CI".equals(System.getenv("ENV"))); // remainder of test }

@Test void testInAllEnvironments() { assumingThat("CI".equals(System.getenv("ENV")), () -> { assertEquals(2, 2); });

// perform these assertions in all environments assertEquals("a string", "a string");

Assumptions

JUnit 5 comes with a subset of the assumption methods that JUnit 4 provides and adds a few that lend themselves well to being used with Java 8 lambdas.

Page 10: JUnit 5 - The Next Generation of JUnit - Ted's Tool Time

import org.junit.gen5.api.*;

@Tag("fast")@Tag("model")class TaggingDemo {

@Test @Tag("taxes") void testingTaxCalculation() { }

}

Tagging and filtering

Tags can be used to filter test discovery and execution.

Page 11: JUnit 5 - The Next Generation of JUnit - Ted's Tool Time

@DisplayName("A stack")class TestingAStack { @Test @DisplayName("is instantiated with new Stack()") void isInstantiatedWithNew() { /*...*/ } @Nested @DisplayName("when new") class WhenNew { @Test @DisplayName("is empty") void isEmpty() { /*...*/ }

Nesting Tests

@Nested @DisplayName("after pushing an element") class AfterPushing { @Test @DisplayName("it is no longer empty") void isEmpty() { /*...*/ } @Test @DisplayName("returns the element when poppe...") void returnElementWhenPopped() { /*...*/ } @Test @DisplayName( "returns the element when peeked but ...") void returnElementWhenPeeked(){ /*...*/ } } }

@DisplayName for readable classes and methods

Source: http://blog.codefx.org/libraries/junit-5-basics/

Page 12: JUnit 5 - The Next Generation of JUnit - Ted's Tool Time

public static class HasTempFolder {@Rulepublic TemporaryFolder folder= new TemporaryFolder();

@Testpublic void testUsingTempFolder() throws IOException {

File createdFile= folder.newFile("myfile.txt");File createdFolder=

folder.newFolder("subfolder");// ...

}}

Source: http://blog.codefx.org/design/architecture/junit-5-extension-model/

How it was done in JUnit 4.

Page 13: JUnit 5 - The Next Generation of JUnit - Ted's Tool Time

How it is done in JUnit 5.

● Test Instance Post Processing

● BeforeAll Callback

● Conditional Test Execution

● BeforeEach Callback

● Parameter Resolution

● Exception Handling

● AfterEach Callback

● AfterAll Callback

Page 14: JUnit 5 - The Next Generation of JUnit - Ted's Tool Time

@ExtendWith(MockitoExtension.class)class MockTests { // ...}

Extensions API

Extensions can be registered declaratively via @ExtendWith. @ExtendWith({ FooExtension.class, BarExtension.class })

class MyTestsV1 { // ...}

Page 15: JUnit 5 - The Next Generation of JUnit - Ted's Tool Time

public class BenchmarkExtension implementsBeforeAllExtensionPoint,

BeforeEachExtensionPoint,AfterEachExtensionPoint,

AfterAllExtensionPoint {

private static final Namespace NAMESPACE =

Namespace.of("BenchmarkExtension");

@Overridepublic void beforeAll(ContainerExtensionContext context) {

if (!shouldBeBenchmarked(context))return;

writeCurrentTime(context,

LaunchTimeKey.CLASS);}

@Overridepublic void beforeEach(TestExtensionContext context) {

if (!shouldBeBenchmarked(context))

Example: BenchmarkExtension

Source: http://blog.codefx.org/design/architecture/junit-5-extension-model/

@Overridepublic void afterEach(TestExtensionContext context) {

if (!shouldBeBenchmarked(context))return;

long launchTime = loadLaunchTime(context,

LaunchTimeKey.TEST);long runtime = currentTimeMillis() - launchTime;print("Test", context.getDisplayName(), runtime);

}

private static boolean shouldBeBenchmarked(ExtensionContext context) {

return context.getElement().isAnnotationPresent(Benchmark.class);

}

private static void writeCurrentTime(ExtensionContext context,

LaunchTimeKey key) {context.getStore(NAMESPACE).put(key,

currentTimeMillis());}

Interfaces

Pass context

Store information

Page 16: JUnit 5 - The Next Generation of JUnit - Ted's Tool Time

References

●JUnit 5http://junit.org/junit5/http://junit.org/junit5/docs/current/user-guide/

●Open Test Alliance for the JVMhttps://github.com/ota4j-team/opentest4j

●Articleshttp://www.codeaffine.com/2016/02/18/junit-5-first-look/http://blog.codefx.org/libraries/junit-5-setup/

Thank you