Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
#40: First steps toward container events in JUnit 4
- ExecutionEventRecordingEngineExecutionListener records all events, i.e. calls of a listener methods, and makes them available to tests. - ExecutionEvent represents such an event. - ExecutionEventConditions contains a collection of AssertJ conditions to write assertions for ExecutionEvents. - FunctionUtils collects utility methods for working with java.util.function.*. ------------------------------------------------------------------------ On behalf of the community, the JUnit Lambda Team thanks msg systems ag (http://www.msg-systems.com) for supporting the JUnit crowdfunding campaign! ------------------------------------------------------------------------
- Loading branch information
1 parent
9d665a0
commit 0f9f29a
Showing
8 changed files
with
349 additions
and
7 deletions.
There are no files selected for viewing
41 changes: 41 additions & 0 deletions
41
junit-commons/src/main/java/org/junit/gen5/commons/util/FunctionUtils.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
/* | ||
* Copyright 2015-2016 the original author or authors. | ||
* | ||
* All rights reserved. This program and the accompanying materials are | ||
* made available under the terms of the Eclipse Public License v1.0 which | ||
* accompanies this distribution and is available at | ||
* | ||
* http://www.eclipse.org/legal/epl-v10.html | ||
*/ | ||
|
||
package org.junit.gen5.commons.util; | ||
|
||
import java.util.function.Function; | ||
import java.util.function.Predicate; | ||
|
||
/** | ||
* Collection of utilities for working with {@link Function Functions}, | ||
* {@link Predicate Predicates}, etc. | ||
* | ||
* @since 5.0 | ||
*/ | ||
public class FunctionUtils { | ||
|
||
private FunctionUtils() { | ||
/* no-op */ | ||
} | ||
|
||
/** | ||
* Returns a predicate that first applies the specified function and then | ||
* tests the specified predicate against the result of the function. | ||
* | ||
* @param function the function to apply | ||
* @param predicate the predicate to test against the result of the function | ||
*/ | ||
public static <T, V> Predicate<T> where(Function<T, V> function, Predicate<? super V> predicate) { | ||
Preconditions.notNull(function, "function must not be null"); | ||
Preconditions.notNull(predicate, "predicate must not be null"); | ||
return input -> predicate.test(function.apply(input)); | ||
} | ||
|
||
} |
45 changes: 45 additions & 0 deletions
45
junit-tests/src/test/java/org/junit/gen5/commons/util/FunctionUtilsTests.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
/* | ||
* Copyright 2015-2016 the original author or authors. | ||
* | ||
* All rights reserved. This program and the accompanying materials are | ||
* made available under the terms of the Eclipse Public License v1.0 which | ||
* accompanies this distribution and is available at | ||
* | ||
* http://www.eclipse.org/legal/epl-v10.html | ||
*/ | ||
|
||
package org.junit.gen5.commons.util; | ||
|
||
import static java.util.function.Predicate.isEqual; | ||
import static org.junit.gen5.api.Assertions.*; | ||
|
||
import java.util.function.Predicate; | ||
|
||
import org.junit.gen5.api.Test; | ||
|
||
class FunctionUtilsTests { | ||
|
||
@Test | ||
void whereWithNullFunction() { | ||
IllegalArgumentException exception = expectThrows(IllegalArgumentException.class, () -> { | ||
FunctionUtils.where(null, o -> true); | ||
}); | ||
assertEquals("function must not be null", exception.getMessage()); | ||
} | ||
|
||
@Test | ||
void whereWithNullPredicate() { | ||
IllegalArgumentException exception = expectThrows(IllegalArgumentException.class, () -> { | ||
FunctionUtils.where(o -> o, null); | ||
}); | ||
assertEquals("predicate must not be null", exception.getMessage()); | ||
} | ||
|
||
@Test | ||
void whereWithChecksPredicateAgainstResultOfFunction() { | ||
Predicate<String> combinedPredicate = FunctionUtils.where(String::length, isEqual(3)); | ||
assertFalse(combinedPredicate.test("fo")); | ||
assertTrue(combinedPredicate.test("foo")); | ||
assertFalse(combinedPredicate.test("fooo")); | ||
} | ||
} |
95 changes: 95 additions & 0 deletions
95
junit-tests/src/test/java/org/junit/gen5/engine/ExecutionEvent.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
/* | ||
* Copyright 2015-2016 the original author or authors. | ||
* | ||
* All rights reserved. This program and the accompanying materials are | ||
* made available under the terms of the Eclipse Public License v1.0 which | ||
* accompanies this distribution and is available at | ||
* | ||
* http://www.eclipse.org/legal/epl-v10.html | ||
*/ | ||
|
||
package org.junit.gen5.engine; | ||
|
||
import static java.util.function.Predicate.isEqual; | ||
import static org.junit.gen5.commons.util.FunctionUtils.where; | ||
import static org.junit.gen5.engine.ExecutionEvent.Type.*; | ||
|
||
import java.util.Optional; | ||
import java.util.function.Predicate; | ||
|
||
import org.junit.gen5.commons.util.ToStringBuilder; | ||
|
||
/** | ||
* Represents an event collected by | ||
* {@link ExecutionEventRecordingEngineExecutionListener}. | ||
* | ||
* @see ExecutionEventConditions | ||
*/ | ||
public class ExecutionEvent { | ||
|
||
public enum Type { | ||
DYNAMIC_TEST_REGISTERED, SKIPPED, STARTED, FINISHED | ||
} | ||
|
||
public static ExecutionEvent dynamicTestRegistered(TestDescriptor testDescriptor) { | ||
return new ExecutionEvent(DYNAMIC_TEST_REGISTERED, testDescriptor, null); | ||
} | ||
|
||
public static ExecutionEvent executionSkipped(TestDescriptor testDescriptor, String reason) { | ||
return new ExecutionEvent(SKIPPED, testDescriptor, reason); | ||
} | ||
|
||
public static ExecutionEvent executionStarted(TestDescriptor testDescriptor) { | ||
return new ExecutionEvent(STARTED, testDescriptor, null); | ||
} | ||
|
||
public static ExecutionEvent executionFinished(TestDescriptor testDescriptor, TestExecutionResult result) { | ||
return new ExecutionEvent(FINISHED, testDescriptor, result); | ||
} | ||
|
||
public static Predicate<ExecutionEvent> byType(ExecutionEvent.Type type) { | ||
return where(ExecutionEvent::getType, isEqual(type)); | ||
} | ||
|
||
public static Predicate<ExecutionEvent> byTestDescriptor(Predicate<? super TestDescriptor> predicate) { | ||
return where(ExecutionEvent::getTestDescriptor, predicate); | ||
} | ||
|
||
public static <T> Predicate<ExecutionEvent> byPayload(Class<T> payloadClass, Predicate<? super T> predicate) { | ||
return event -> event.getPayload(payloadClass).filter(predicate).isPresent(); | ||
} | ||
|
||
private final ExecutionEvent.Type type; | ||
private final TestDescriptor testDescriptor; | ||
private final Object payload; | ||
|
||
private ExecutionEvent(ExecutionEvent.Type type, TestDescriptor testDescriptor, Object payload) { | ||
this.type = type; | ||
this.testDescriptor = testDescriptor; | ||
this.payload = payload; | ||
} | ||
|
||
public ExecutionEvent.Type getType() { | ||
return type; | ||
} | ||
|
||
public TestDescriptor getTestDescriptor() { | ||
return testDescriptor; | ||
} | ||
|
||
public <T> Optional<T> getPayload(Class<T> payloadClass) { | ||
return Optional.ofNullable(payload).filter(payloadClass::isInstance).map(payloadClass::cast); | ||
} | ||
|
||
@Override | ||
public String toString() { | ||
// @formatter:off | ||
return new ToStringBuilder(this) | ||
.append("type", type) | ||
.append("testDescriptor", testDescriptor) | ||
.append("payload", payload) | ||
.toString(); | ||
// @formatter:on | ||
} | ||
|
||
} |
60 changes: 60 additions & 0 deletions
60
junit-tests/src/test/java/org/junit/gen5/engine/ExecutionEventConditions.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
/* | ||
* Copyright 2015-2016 the original author or authors. | ||
* | ||
* All rights reserved. This program and the accompanying materials are | ||
* made available under the terms of the Eclipse Public License v1.0 which | ||
* accompanies this distribution and is available at | ||
* | ||
* http://www.eclipse.org/legal/epl-v10.html | ||
*/ | ||
|
||
package org.junit.gen5.engine; | ||
|
||
import static org.assertj.core.api.Assertions.allOf; | ||
import static org.junit.gen5.engine.ExecutionEvent.*; | ||
import static org.junit.gen5.engine.ExecutionEvent.Type.*; | ||
import static org.junit.gen5.engine.TestExecutionResult.Status.*; | ||
import static org.junit.gen5.engine.TestExecutionResultConditions.status; | ||
|
||
import org.assertj.core.api.Condition; | ||
import org.junit.gen5.engine.ExecutionEvent.Type; | ||
|
||
/** | ||
* Collection of AssertJ conditions for {@link ExecutionEvent}. | ||
*/ | ||
public class ExecutionEventConditions { | ||
|
||
public static Condition<ExecutionEvent> test() { | ||
return new Condition<>(byTestDescriptor(TestDescriptor::isTest), "is a test"); | ||
} | ||
|
||
public static Condition<ExecutionEvent> container() { | ||
return new Condition<>(byTestDescriptor(TestDescriptor::isContainer), "is a container"); | ||
} | ||
|
||
public static Condition<ExecutionEvent> started() { | ||
return type(STARTED); | ||
} | ||
|
||
public static Condition<ExecutionEvent> finishedWithFailure(Condition<TestExecutionResult> causeMessage) { | ||
return finished(allOf(status(FAILED), causeMessage)); | ||
} | ||
|
||
public static Condition<ExecutionEvent> finishedSuccessfully() { | ||
return finished(status(SUCCESSFUL)); | ||
} | ||
|
||
public static Condition<ExecutionEvent> finished(Condition<TestExecutionResult> resultCondition) { | ||
return allOf(type(FINISHED), result(resultCondition)); | ||
} | ||
|
||
public static Condition<ExecutionEvent> type(Type expectedType) { | ||
return new Condition<>(byType(expectedType), "type is %s", expectedType); | ||
} | ||
|
||
public static Condition<ExecutionEvent> result(Condition<TestExecutionResult> condition) { | ||
return new Condition<>(byPayload(TestExecutionResult.class, condition::matches), "event with result where %s", | ||
condition); | ||
} | ||
|
||
} |
54 changes: 54 additions & 0 deletions
54
...s/src/test/java/org/junit/gen5/engine/ExecutionEventRecordingEngineExecutionListener.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
/* | ||
* Copyright 2015-2016 the original author or authors. | ||
* | ||
* All rights reserved. This program and the accompanying materials are | ||
* made available under the terms of the Eclipse Public License v1.0 which | ||
* accompanies this distribution and is available at | ||
* | ||
* http://www.eclipse.org/legal/epl-v10.html | ||
*/ | ||
|
||
package org.junit.gen5.engine; | ||
|
||
import java.util.List; | ||
import java.util.concurrent.CopyOnWriteArrayList; | ||
|
||
/** | ||
* {@link EngineExecutionListener} that records all events and makes them | ||
* available to tests. | ||
* | ||
* @see ExecutionEvent | ||
*/ | ||
public class ExecutionEventRecordingEngineExecutionListener implements EngineExecutionListener { | ||
|
||
public final List<ExecutionEvent> executionEvents = new CopyOnWriteArrayList<>(); | ||
|
||
@Override | ||
public void dynamicTestRegistered(TestDescriptor testDescriptor) { | ||
addEvent(ExecutionEvent.dynamicTestRegistered(testDescriptor)); | ||
} | ||
|
||
@Override | ||
public void executionSkipped(TestDescriptor testDescriptor, String reason) { | ||
addEvent(ExecutionEvent.executionSkipped(testDescriptor, reason)); | ||
} | ||
|
||
@Override | ||
public void executionStarted(TestDescriptor testDescriptor) { | ||
addEvent(ExecutionEvent.executionStarted(testDescriptor)); | ||
} | ||
|
||
@Override | ||
public void executionFinished(TestDescriptor testDescriptor, TestExecutionResult result) { | ||
addEvent(ExecutionEvent.executionFinished(testDescriptor, result)); | ||
} | ||
|
||
public List<ExecutionEvent> getExecutionEvents() { | ||
return executionEvents; | ||
} | ||
|
||
private void addEvent(ExecutionEvent dynamicTestRegistered) { | ||
executionEvents.add(dynamicTestRegistered); | ||
} | ||
|
||
} |
35 changes: 35 additions & 0 deletions
35
junit-tests/src/test/java/org/junit/gen5/engine/TestExecutionResultConditions.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
/* | ||
* Copyright 2015-2016 the original author or authors. | ||
* | ||
* All rights reserved. This program and the accompanying materials are | ||
* made available under the terms of the Eclipse Public License v1.0 which | ||
* accompanies this distribution and is available at | ||
* | ||
* http://www.eclipse.org/legal/epl-v10.html | ||
*/ | ||
|
||
package org.junit.gen5.engine; | ||
|
||
import static java.util.function.Predicate.isEqual; | ||
import static org.junit.gen5.commons.util.FunctionUtils.where; | ||
|
||
import org.assertj.core.api.Condition; | ||
import org.junit.gen5.engine.TestExecutionResult.Status; | ||
|
||
/** | ||
* Collection of AssertJ conditions for {@link TestExecutionResult}. | ||
*/ | ||
public class TestExecutionResultConditions { | ||
|
||
public static Condition<TestExecutionResult> status(Status expectedStatus) { | ||
return new Condition<>(where(TestExecutionResult::getStatus, isEqual(expectedStatus)), "status is %s", | ||
expectedStatus); | ||
} | ||
|
||
public static Condition<TestExecutionResult> causeMessage(String expectedMessage) { | ||
return new Condition<TestExecutionResult>(where(TestExecutionResult::getThrowable, throwable -> { | ||
return throwable.isPresent() && expectedMessage.equals(throwable.get().getMessage()); | ||
}), "message of cause is %s", expectedMessage); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.