How can an extension add to the output of a test? #5996
|
I am writing an extension to inject The problem I am facing is that the extension has to report the random seed in case of test failure. Important goals:
Am I trying something impossible, or am I missing the intended approach? |
Replies: 5 comments 2 replies
|
The piece you're missing is The contract is explicit about what you may do with the throwable: Option 2 with a suppressed exception attached is what fits your goal, since the seed then travels with the failure rather than as separate output: class RandomSeedExtension implements ParameterResolver, TestExecutionExceptionHandler {
private static final Namespace NS = Namespace.create(RandomSeedExtension.class);
@Override
public Object resolveParameter(ParameterContext pc, ExtensionContext ctx) {
long seed = ...;
ctx.getStore(NS).put("seed", seed);
return new Random(seed);
}
@Override
public void handleTestExecutionException(ExtensionContext ctx, Throwable t) throws Throwable {
Long seed = ctx.getStore(NS).get("seed", Long.class);
if (seed != null) {
t.addSuppressed(new IllegalStateException("random seed = " + seed));
}
throw t;
}
}Suppressed exceptions are printed as part of the stack trace, so Gradle keeps them in the failure details and IntelliJ shows them under the failure rather than in a separate stdout tab. That covers the ordering problem you hit with Two related notes. If the seed also matters when a failure comes from
|
|
Adding a suppressed exception seems like an abuse to me, because:
But ah well if a suppressed exception is the one way to deal with that, then so be it. I'm considering workarounds for the two above artifacts:
Comments, perspectives, criticism, feedback welcome :-) (No need to deal with |
|
Works as designed. Gradle output: No idea why Gradle is adding these copious amounts of blank lines, but I seem to recall that it has always been that way. The Gradle report looks exactly as it should: So - all is fine, except I still find it annoying to have to write that |
|
You don't need to override much. public final class Info extends RuntimeException {
public Info(String message) {
super(message, null, false, false); // no suppression, no writable stack trace
}
@Override
public String toString() {
return getMessage();
}
}That gets you On the success case, |
|
BTW yeah console output is important. Actually, now that I think of it, I have a strong feeling that nobody should use the reporting API for any data that's for human consumption. Data that's exclusively consumed by machines, such as formatting hints, raw statistic data, and similar, seem fine to me. |
The piece you're missing is
TestExecutionExceptionHandler. It runs while the failure is still in flight, which is the only point where you can attach something that ends up inside the failure itself rather than beside it.The contract is explicit about what you may do with the throwable:
Option 2 with a suppressed exception attached is what fits your goal, since the seed then travels with the failure rather than as separate output: