Skip to content

Commit fd699ca

Browse files
committed
feat: #213 Provide TestResult assertion helpers
Signed-off-by: Laurent Broudoux <laurent.broudoux@gmail.com>
1 parent 4ce2d6d commit fd699ca

File tree

3 files changed

+328
-2
lines changed

3 files changed

+328
-2
lines changed

pom.xml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,13 +67,12 @@
6767
<artifactId>testcontainers</artifactId>
6868
<version>${testcontainers.version}</version>
6969
</dependency>
70-
7170
<dependency>
7271
<groupId>org.junit.jupiter</groupId>
7372
<artifactId>junit-jupiter-api</artifactId>
7473
<version>${jupiter.version}</version>
75-
<scope>test</scope>
7674
</dependency>
75+
7776
<dependency>
7877
<groupId>org.junit.jupiter</groupId>
7978
<artifactId>junit-jupiter-params</artifactId>
Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
package io.github.microcks.testcontainers;
2+
3+
import io.github.microcks.testcontainers.model.TestResult;
4+
5+
import org.junit.jupiter.api.AssertionFailureBuilder;
6+
import org.opentest4j.AssertionFailedError;
7+
import org.opentest4j.MultipleFailuresError;
8+
9+
import java.util.ArrayList;
10+
import java.util.List;
11+
import java.util.concurrent.atomic.AtomicBoolean;
12+
13+
/**
14+
* Assertion helpers for easily checking TestResult instances.
15+
* @author laurent
16+
*/
17+
public class Assertions {
18+
19+
/**
20+
* Assert that the given test result is a success. If not, throw an AssertionFailedError with all the
21+
* underlying failures from all the test steps in test cases.
22+
* @param testResult The test result to check
23+
*/
24+
public static void assertSuccess(TestResult testResult) {
25+
List<Throwable> failures = new ArrayList<>();
26+
if (!testResult.isSuccess()) {
27+
testResult.getTestCaseResults().stream()
28+
.filter(testCaseResult -> !testCaseResult.isSuccess())
29+
.forEach(testCaseResult -> testCaseResult.getTestStepResults().stream()
30+
.filter(testStepResult -> !testResult.isSuccess())
31+
.forEach(testStepResult -> {
32+
AssertionFailedError failureError = AssertionFailureBuilder.assertionFailure()
33+
.message("Message '" + testStepResult.getRequestName() + "' of operation '"
34+
+ testCaseResult.getOperationName() + "' failed")
35+
.reason(String.join(" && ", testStepResult.getMessage().split("\n")))
36+
.build();
37+
38+
failures.add(failureError);
39+
}));
40+
41+
if (!failures.isEmpty()) {
42+
throw new MultipleFailuresError("Test '" + testResult.getId() + "' has failed", failures);
43+
}
44+
}
45+
}
46+
47+
/**
48+
* Assert that the given test result has succeeded for the given operation name. If not, throw an
49+
* AssertionFailedError with all the underlying failures from all the test steps in the test case
50+
* @param testResult The test result to check
51+
* @param operationName The operation name to check (ie. the test case name)
52+
*/
53+
public static void assertSuccess(TestResult testResult, String operationName) {
54+
AtomicBoolean foundTestCase = new AtomicBoolean(false);
55+
testResult.getTestCaseResults().stream()
56+
.filter(testCase -> testCase.getOperationName().equalsIgnoreCase(operationName))
57+
.forEach(testCase -> {
58+
foundTestCase.set(true);
59+
if (!testCase.isSuccess()) {
60+
List<Throwable> failures = new ArrayList<>();
61+
testCase.getTestStepResults().stream()
62+
.filter(testStep -> !testStep.isSuccess())
63+
.forEach(testStep -> {
64+
AssertionFailedError failureError = AssertionFailureBuilder.assertionFailure()
65+
.message("Message '" + testStep.getRequestName() + "' of operation '"
66+
+ testCase.getOperationName() + "' failed")
67+
.reason(String.join(" && ", testStep.getMessage().split("\n")))
68+
.build();
69+
70+
failures.add(failureError);
71+
});
72+
if (!failures.isEmpty()) {
73+
throw new MultipleFailuresError("Test '" + testResult.getId() + "' for operation '"
74+
+ operationName + "' has failed", failures);
75+
}
76+
}
77+
});
78+
if (!foundTestCase.get()) {
79+
throw new AssertionFailedError("Test '" + testResult.getId() + "' has no test case for operation '"
80+
+ operationName + "'");
81+
}
82+
}
83+
84+
/**
85+
* Assert that the given test result has succeeded for the given operation name and message name. If not, throw an
86+
* AssertionFailedError.
87+
* @param testResult The test result to check
88+
* @param operationName The operation name to check (ie. the test case name)
89+
* @param messageName The message name to check (ie. the test step name)
90+
*/
91+
public static void assertSuccess(TestResult testResult, String operationName, String messageName) {
92+
AtomicBoolean foundTestCase = new AtomicBoolean(false);
93+
AtomicBoolean foundTestStep = new AtomicBoolean(false);
94+
testResult.getTestCaseResults().stream()
95+
.filter(testCase -> testCase.getOperationName().equalsIgnoreCase(operationName))
96+
.forEach(testCase -> {
97+
foundTestCase.set(true);
98+
testCase.getTestStepResults().stream()
99+
.filter(testStep -> testStep.getRequestName().equalsIgnoreCase(messageName))
100+
.forEach(testStep -> {
101+
foundTestStep.set(true);
102+
if (!testStep.isSuccess()) {
103+
throw new AssertionFailedError("Test '" + testResult.getId() + "' for operation '"
104+
+ operationName + "' and message '" + messageName + "' has failed: "
105+
+ testStep.getMessage());
106+
}
107+
});
108+
if (!foundTestStep.get()) {
109+
throw new AssertionFailedError("Test '" + testResult.getId() + "' has no test step for operation '"
110+
+ operationName + "' and message '" + messageName + "'");
111+
}
112+
});
113+
if (!foundTestCase.get()) {
114+
throw new AssertionFailedError("Test '" + testResult.getId() + "' has no test case for operation '"
115+
+ operationName + "'");
116+
}
117+
}
118+
119+
/**
120+
* Assert that the given test result has failed for the given operation name. If not, throw an
121+
* AssertionFailedError.
122+
* @param testResult The test result to check
123+
* @param operationName The operation name to check (ie. the test case name)
124+
*/
125+
public static void assertFailure(TestResult testResult, String operationName) {
126+
AtomicBoolean foundTestCase = new AtomicBoolean(false);
127+
testResult.getTestCaseResults().stream()
128+
.filter(testCase -> testCase.getOperationName().equalsIgnoreCase(operationName))
129+
.forEach(testCase -> {
130+
foundTestCase.set(true);
131+
if (testCase.isSuccess()) {
132+
throw new AssertionFailedError("Test '" + testResult.getId() + "' for operation '"
133+
+ operationName + "' should have failed");
134+
}
135+
});
136+
if (!foundTestCase.get()) {
137+
throw new AssertionFailedError("Test '" + testResult.getId() + "' has no test case for operation '"
138+
+ operationName + "'");
139+
}
140+
}
141+
142+
/**
143+
* Assert that the given test result has failed for the given operation name and message name. If not, throw an
144+
* AssertionFailedError.
145+
* @param testResult The test result to check
146+
* @param operationName The operation name to check (ie. the test case name)
147+
* @param messageName The message name to check (ie. the test step name)
148+
*/
149+
public static void assertFailure(TestResult testResult, String operationName, String messageName) {
150+
AtomicBoolean foundTestCase = new AtomicBoolean(false);
151+
AtomicBoolean foundTestStep = new AtomicBoolean(false);
152+
testResult.getTestCaseResults().stream()
153+
.filter(testCase -> testCase.getOperationName().equalsIgnoreCase(operationName))
154+
.forEach(testCase -> {
155+
foundTestCase.set(true);
156+
testCase.getTestStepResults().stream()
157+
.filter(testStep -> testStep.getRequestName().equalsIgnoreCase(messageName))
158+
.forEach(testStep -> {
159+
foundTestStep.set(true);
160+
if (testStep.isSuccess()) {
161+
throw new AssertionFailedError("Test '" + testResult.getId() + "' for operation '"
162+
+ operationName + "' and message '" + messageName + "' should have failed");
163+
}
164+
return;
165+
});
166+
if (!foundTestStep.get()) {
167+
throw new AssertionFailedError("Test '" + testResult.getId() + "' has no test step for operation '"
168+
+ operationName + "' and message '" + messageName + "'");
169+
}
170+
});
171+
if (!foundTestCase.get()) {
172+
throw new AssertionFailedError("Test '" + testResult.getId() + "' has no test case for operation '"
173+
+ operationName + "'");
174+
}
175+
}
176+
}
Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
package io.github.microcks.testcontainers;
2+
3+
import io.github.microcks.testcontainers.model.TestCaseResult;
4+
import io.github.microcks.testcontainers.model.TestResult;
5+
import io.github.microcks.testcontainers.model.TestStepResult;
6+
7+
import org.junit.jupiter.api.Test;
8+
import org.opentest4j.AssertionFailedError;
9+
import org.opentest4j.MultipleFailuresError;
10+
11+
import java.util.List;
12+
13+
import static org.junit.jupiter.api.Assertions.*;
14+
15+
/**
16+
* Test class for Assertions.
17+
* @author laurent
18+
*/
19+
public class AssertionsTest {
20+
21+
@Test
22+
void testFullSuccess() {
23+
TestResult result = new TestResult();
24+
result.setSuccess(true);
25+
26+
Assertions.assertSuccess(result);
27+
}
28+
29+
@Test
30+
void testPartialSuccess() {
31+
TestResult result = new TestResult();
32+
result.setId("testPartialSuccess");
33+
result.setSuccess(false);
34+
35+
TestCaseResult case1 = new TestCaseResult();
36+
case1.setOperationName("op1");
37+
case1.setSuccess(true);
38+
TestStepResult step11 = new TestStepResult();
39+
step11.setRequestName("req11");
40+
step11.setSuccess(true);
41+
case1.setTestStepResults(List.of(step11));
42+
43+
TestCaseResult case2 = new TestCaseResult();
44+
case2.setOperationName("op2");
45+
case2.setSuccess(false);
46+
TestStepResult step21 = new TestStepResult();
47+
step21.setRequestName("req21");
48+
step21.setSuccess(false);
49+
step21.setMessage("Not matching");
50+
case2.setTestStepResults(List.of(step21));
51+
52+
result.setTestCaseResults(List.of(case1, case2));
53+
54+
boolean failed = false;
55+
try {
56+
Assertions.assertSuccess(result);
57+
} catch (Error error) {
58+
failed = true;
59+
assertInstanceOf(MultipleFailuresError.class, error);
60+
MultipleFailuresError mfe = (MultipleFailuresError)error;
61+
assertTrue(mfe.getMessage().startsWith("Test 'testPartialSuccess' has failed (1 failure)"));
62+
63+
List<Throwable> failures = mfe.getFailures();
64+
assertEquals(1, failures.size());
65+
assertTrue(failures.get(0).getMessage().equals("Message 'req21' of operation 'op2' failed ==> Not matching"));
66+
}
67+
if (!failed) {
68+
fail("An AssertionFailedError should have been thrown");
69+
}
70+
71+
// Check for operation-specific assertion.
72+
Assertions.assertSuccess(result, "op1");
73+
Assertions.assertSuccess(result, "op1", "req11");
74+
75+
failed = false;
76+
try {
77+
Assertions.assertSuccess(result, "op2");
78+
} catch (Error error) {
79+
failed = true;
80+
assertInstanceOf(MultipleFailuresError.class, error);
81+
MultipleFailuresError mfe = (MultipleFailuresError)error;
82+
assertTrue(mfe.getMessage().startsWith("Test 'testPartialSuccess' for operation 'op2' has failed (1 failure)"));
83+
84+
List<Throwable> failures = mfe.getFailures();
85+
assertEquals(1, failures.size());
86+
assertEquals("Message 'req21' of operation 'op2' failed ==> Not matching", failures.get(0).getMessage());
87+
}
88+
if (!failed) {
89+
fail("An AssertionFailedError should have been thrown");
90+
}
91+
92+
failed = false;
93+
try {
94+
Assertions.assertSuccess(result, "op1", "req12");
95+
} catch (Error error) {
96+
failed = true;
97+
assertInstanceOf(AssertionFailedError.class, error);
98+
assertEquals("Test 'testPartialSuccess' has no test step for operation 'op1' and message 'req12'", error.getMessage());
99+
}
100+
if (!failed) {
101+
fail("An AssertionFailedError should have been thrown");
102+
}
103+
}
104+
105+
@Test
106+
void testPartialFailure() {
107+
TestResult result = new TestResult();
108+
result.setId("testPartialFailure");
109+
result.setSuccess(false);
110+
111+
TestCaseResult case1 = new TestCaseResult();
112+
case1.setOperationName("op1");
113+
case1.setSuccess(true);
114+
TestCaseResult case2 = new TestCaseResult();
115+
case2.setOperationName("op2");
116+
case2.setSuccess(false);
117+
TestStepResult step21 = new TestStepResult();
118+
step21.setRequestName("req21");
119+
step21.setSuccess(false);
120+
step21.setMessage("Not matching");
121+
case2.setTestStepResults(List.of(step21));
122+
result.setTestCaseResults(List.of(case1, case2));
123+
124+
Assertions.assertFailure(result, "op2");
125+
Assertions.assertFailure(result, "op2", "req21");
126+
127+
boolean failed = false;
128+
try {
129+
Assertions.assertFailure(result, "op1");
130+
} catch (Error error) {
131+
failed = true;
132+
assertInstanceOf(AssertionFailedError.class, error);
133+
assertEquals("Test 'testPartialFailure' for operation 'op1' should have failed", error.getMessage());
134+
}
135+
if (!failed) {
136+
fail("An AssertionFailedError should have been thrown");
137+
}
138+
139+
failed = false;
140+
try {
141+
Assertions.assertFailure(result, "op2", "req22");
142+
} catch (Error error) {
143+
failed = true;
144+
assertInstanceOf(AssertionFailedError.class, error);
145+
assertEquals("Test 'testPartialFailure' has no test step for operation 'op2' and message 'req22'", error.getMessage());
146+
}
147+
if (!failed) {
148+
fail("An AssertionFailedError should have been thrown");
149+
}
150+
}
151+
}

0 commit comments

Comments
 (0)