Skip to content

Commit d4e721a

Browse files
committed
Improve handling of MultipleFailuresError
1 parent 7abfc9a commit d4e721a

File tree

3 files changed

+92
-70
lines changed

3 files changed

+92
-70
lines changed

Diff for: spock-core/src/main/java/org/spockframework/runtime/MasterRunSupervisor.java

+29-24
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,10 @@
44
import org.spockframework.runtime.model.*;
55
import org.spockframework.util.*;
66

7-
import org.junit.internal.AssumptionViolatedException;
8-
import org.junit.runners.model.MultipleFailureException;
9-
import org.opentest4j.*;
7+
import java.util.List;
8+
import java.util.stream.*;
109

11-
import static org.spockframework.runtime.RunStatus.OK;
10+
import org.opentest4j.*;
1211

1312
class MasterRunSupervisor implements IRunSupervisor {
1413

@@ -42,31 +41,37 @@ public void beforeIteration(IterationInfo iteration) {
4241
public int error(ErrorInfo error) {
4342
Throwable exception = error.getException();
4443

45-
// if (exception instanceof MultipleFailureException) // TODO move to junit4 extension?
46-
// return handleMultipleFailures(error);
47-
//
48-
if (isFailedEqualityComparison(exception))
49-
exception = convertToComparisonFailure(exception);
44+
if (exception instanceof MultipleFailuresError) {
45+
List<Throwable> failures = expandMultipleFailuresError(exception)
46+
.map(this::transform).collect(Collectors.toList());
5047

51-
filter.filter(exception);
48+
exception = failures.size() == 1 ? failures.get(0) : new MultipleFailuresError(exception.getMessage(), failures);
49+
} else {
50+
exception = transform(exception);
51+
}
5252

53-
if (exception instanceof AssumptionViolatedException) { // TODO move to junit4 extension?
54-
// Spock has no concept of "violated assumption", so we don't notify Spock listeners
55-
// do notify JUnit listeners unless it's a data-driven iteration that's reported as one feature
53+
if (exception instanceof TestAbortedException || exception instanceof TestSkippedException) {
54+
// Spock has no concept of "aborted tests", so we don't notify Spock listeners
5655
} else {
57-
masterListener.error(error);
56+
masterListener.error(new ErrorInfo(error.getMethod(), exception));
5857
}
58+
5959
ExceptionUtil.sneakyThrow(exception);
6060
return 0;
6161
}
6262

63-
// for better JUnit compatibility, e.g when a @Rule is used
64-
private int handleMultipleFailures(ErrorInfo error) {
65-
MultipleFailureException multiFailure = (MultipleFailureException) error.getException();
66-
int runStatus = OK;
67-
for (Throwable failure : multiFailure.getFailures())
68-
runStatus = error(new ErrorInfo(error.getMethod(), failure));
69-
return runStatus;
63+
private Throwable transform(Throwable throwable) {
64+
if (isFailedEqualityComparison(throwable))
65+
throwable = convertToComparisonFailure(throwable);
66+
67+
filter.filter(throwable);
68+
return throwable;
69+
}
70+
71+
private Stream<Throwable> expandMultipleFailuresError(Throwable throwable) {
72+
if (throwable instanceof MultipleFailuresError)
73+
return ((MultipleFailuresError)throwable).getFailures().stream().flatMap(this::expandMultipleFailuresError);
74+
return Stream.of(throwable);
7075
}
7176

7277
private boolean isFailedEqualityComparison(Throwable exception) {
@@ -87,9 +92,9 @@ private Throwable convertToComparisonFailure(Throwable exception) {
8792
Condition condition = conditionNotSatisfiedError.getCondition();
8893
ExpressionInfo expr = condition.getExpression();
8994

90-
ValueWrapper actual = ValueWrapper.create(expr.getChildren().get(0).getValue());
91-
ValueWrapper expected = ValueWrapper.create(expr.getChildren().get(1).getValue());
92-
// TODO check if the new rendering by ValueWrapper is good enough
95+
String actual = renderValue(expr.getChildren().get(0).getValue());
96+
String expected = renderValue(expr.getChildren().get(1).getValue());
97+
// TODO use new ValueWrapper from ota 1.2 with custom rendering support
9398
AssertionFailedError failure = new SpockComparisonFailure(condition, expected, actual);
9499
failure.setStackTrace(exception.getStackTrace());
95100

Diff for: spock-core/src/main/java/org/spockframework/runtime/SpockComparisonFailure.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ public class SpockComparisonFailure extends AssertionFailedError {
2929

3030
private final Condition condition;
3131

32-
public SpockComparisonFailure(Condition condition, ValueWrapper expected, ValueWrapper actual) {
32+
public SpockComparisonFailure(Condition condition, Object expected, Object actual) {
3333
super(null, expected, actual);
3434
this.condition = condition;
3535
}

Diff for: spock-specs/src/test/groovy/org/spockframework/verifyall/VerifyAllSpecification.groovy

+62-45
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,17 @@ class VerifyAllSpecification extends EmbeddedSpecification {
2525
}
2626
}""")
2727
then:
28-
result.failures.size() == 2
29-
with(result.failures[0].exception, SpockComparisonFailure) {
30-
expected.trim() == "2"
31-
actual.trim() == "1"
32-
}
33-
with(result.failures[1].exception, SpockComparisonFailure) {
34-
expected.trim() == "4"
35-
actual.trim() == "3"
28+
result.failures.size() == 1
29+
with(result.failures[0].exception, MultipleFailuresError) {
30+
failures.size() == 2
31+
with(failures[0], SpockComparisonFailure) {
32+
expected.stringRepresentation.trim() == "2"
33+
actual.stringRepresentation.trim() == "1"
34+
}
35+
with(failures[1], SpockComparisonFailure) {
36+
expected.stringRepresentation.trim() == "4"
37+
actual.stringRepresentation.trim() == "3"
38+
}
3639
}
3740
}
3841

@@ -79,16 +82,19 @@ class VerifyAllSpecification extends EmbeddedSpecification {
7982
}
8083
}""")
8184
then:
82-
result.failures.size() == 2
83-
84-
with(result.failures[0].exception, SpockComparisonFailure) {
85-
expected.trim() == "3"
86-
actual.trim() == "2"
87-
}
88-
with(result.failures[1].exception, SpockComparisonFailure) {
89-
expected.trim() == "4"
90-
actual.trim() == "3"
85+
result.failures.size() == 1
86+
with(result.failures[0].exception, MultipleFailuresError) {
87+
failures.size() == 2
88+
with(failures[0], SpockComparisonFailure) {
89+
expected.stringRepresentation.trim() == "3"
90+
actual.stringRepresentation.trim() == "2"
91+
}
92+
with(failures[1], SpockComparisonFailure) {
93+
expected.stringRepresentation.trim() == "4"
94+
actual.stringRepresentation.trim() == "3"
95+
}
9196
}
97+
9298
}
9399
94100
def "verifyAll with target and failures"() {
@@ -108,14 +114,17 @@ class VerifyAllSpecification extends EmbeddedSpecification {
108114
}
109115
}""")
110116
then:
111-
result.failures.size() == 2
112-
with(result.failures[0].exception, SpockComparisonFailure) {
113-
expected.trim() == "Bob"
114-
actual.trim() == "Fred"
115-
}
116-
with(result.failures[1].exception, SpockComparisonFailure) {
117-
expected.trim() == "137"
118-
actual.trim() == "42"
117+
result.failures.size() == 1
118+
with(result.failures[0].exception, MultipleFailuresError) {
119+
failures.size() == 2
120+
with(failures[0], SpockComparisonFailure) {
121+
expected.stringRepresentation.trim() == "Bob"
122+
actual.stringRepresentation.trim() == "Fred"
123+
}
124+
with(failures[1], SpockComparisonFailure) {
125+
expected.stringRepresentation.trim() == "137"
126+
actual.stringRepresentation.trim() == "42"
127+
}
119128
}
120129
}
121130
@@ -148,14 +157,18 @@ class VerifyAllSpecification extends EmbeddedSpecification {
148157
}
149158
}""")
150159
then:
151-
result.failures.size() == 2
152-
with(result.failures[0].exception, SpockComparisonFailure) {
153-
expected.trim() == "Bob"
154-
actual.trim() == "Fred"
155-
}
156-
with(result.failures[1].exception, SpockComparisonFailure) {
157-
expected.trim() == "137"
158-
actual.trim() == "42"
160+
161+
result.failures.size() == 1
162+
with(result.failures[0].exception, MultipleFailuresError) {
163+
failures.size() == 2
164+
with(failures[0], SpockComparisonFailure) {
165+
expected.stringRepresentation.trim() == "Bob"
166+
actual.stringRepresentation.trim() == "Fred"
167+
}
168+
with(failures[1], SpockComparisonFailure) {
169+
expected.stringRepresentation.trim() == "137"
170+
actual.stringRepresentation.trim() == "42"
171+
}
159172
}
160173
}
161174
@@ -319,18 +332,22 @@ class VerifyAllSpecification extends EmbeddedSpecification {
319332
}
320333
}""")
321334
then:
322-
result.failures.size() == 3
323-
with(result.failures[0].exception, SpockComparisonFailure) {
324-
expected.trim() == "2"
325-
actual.trim() == "1"
326-
}
327-
with(result.failures[1].exception, SpockComparisonFailure) {
328-
expected.trim() == "4"
329-
actual.trim() == "3"
330-
}
331-
with(result.failures[2].exception, SpockComparisonFailure) {
332-
expected.trim() == "5"
333-
actual.trim() == "4"
335+
336+
result.failures.size() == 1
337+
with(result.failures[0].exception, MultipleFailuresError) {
338+
failures.size() == 3
339+
with(failures[0], SpockComparisonFailure) {
340+
expected.stringRepresentation.trim() == "2"
341+
actual.stringRepresentation.trim() == "1"
342+
}
343+
with(failures[1], SpockComparisonFailure) {
344+
expected.stringRepresentation.trim() == "4"
345+
actual.stringRepresentation.trim() == "3"
346+
}
347+
with(failures[2], SpockComparisonFailure) {
348+
expected.stringRepresentation.trim() == "5"
349+
actual.stringRepresentation.trim() == "4"
350+
}
334351
}
335352
}
336353

0 commit comments

Comments
 (0)