-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Introduce TestWatcher extension API for processing test execution results #542
Comments
Does this need to be a Jupiter extension or would a Platform TestExecutionListener work for you (if there was a more dynamic way to register it as proposed in #19 (comment))? |
From my point of view :
Yes this needs to be a Jupiter extension - because I need to know test result from extension. For now there is no way to do so.
No. Not at the moment Typical use of Launcher launcher = LauncherFactory.create();
launcher.registerTestExecutionListeners(new TestExecutionListener() {
// ...
})
launcher.discover( <---- to discover tests, get TestPlan ...
launcher.execute( <---- actual tests execution launcher object is not accessible from extensions, so for now there is no way yo use it from within an extension object. But if you mean something like this /**
* Callback that is invoked <em>before</em> each test is invoked.
*
* @param context the current extension context; never {@code null}
*/
void beforeEach(TestExtensionContext context) throws Exception {
// context.launcher() <--- new method
context.launcher().registerTestExecutionListeners(....) // < ---- dynamic registering it could work. Nevertheless using this approach the caller must take care of unregistering added listener - all listeners are registered into the same object (added into internal notification list, I suppose). if custom code does not do that unregistration (by mistake) - notification list can be overfilled, (that in turn, results in memory leaks, triggering listeners that are not used... etc, and affect the rest of tests.) context.launcher() <-- seems to be out of its place. Approach with .... public interface TestFinished extends Extension {
void testExecutionFinished(TestIdentifier testIdentifier, TestExtensionContext context,
TestExecutionResult testExecutionResult) throws Exception;
} seems more reliable. |
Let me try to sketch out what I meant in a bit more detail. You would create a JAR with your TestExecutionListener and include a file
The JUnit Platform launcher would look for your listener implementation using the ServiceLoader API (i.e. the same way it finds TestEngines) and register it automatically. You wouldn't have to reference your listener in any of your test cases. It just needs to be on the test runtime classpath. Would that work for you? |
@marcphilipp I apologise in advance if I still misunderstand your point. It does not take much efforts to implement this feature Iterator<TestExecutionListener> providers = Service.providers(TestExecutionListener.class);
while(providers.hasNext()) {
TestExecutionListener listener = providers.next();
listener;// <----
} but it will not give much of advantage. because it is not enough to make class to be aware of test results. (at least I did not find a way). But even though there is a way to make it for instance Could you please clarify what you mean if I still misunderstand you. |
@junit-team/junit-lambda Can one of you chime in? 🤔 |
I think that we in general do need such functionality. For example, in order to implement something like quickcheck as a JUnit Jupiter extension, the extension would need a real-time mechanism for determining whether previously submitted tests (e.g., dynamic tests or parameterized tests) succeeded in order to determine if additional tests should be submitted/generated. The discussion in this issue simply involves a different use case for gaining access to the test execution result. I thought we had discussed this topic elsewhere, but I don't have time to search right now. ;) |
When approximately are you planing to implement it ? |
FYI: People on StackOverflow are also looking for this feature. |
Thanks, I've added a comment there: http://stackoverflow.com/questions/42721422/junit5-how-to-get-test-result-in-aftertestexecutioncallback#comment72608741_42721422 Looking at the test exception is not really reliable. The test might fail in an extension that hasn't been invoked, yet. I think we might need a new extension point that cannot influence the test's result. Any other ideas? |
A comment? Pfft, I made it an answer. 😉
That makes sense, yes. The interesting question is, what else this extension point would be allowed to do. See Sam's comment above:
|
For me, two extension points make sense:
|
I asked this stackoverflow question. I'll try to describe my usecase: We have few tests with custom annotation something like: when this test is executed I want write "specific String" to console. e.g. When we are releasing version. This specific string is parsed and recorded into external system. So i wrote Extension. Which will write this "specific String" to console. Everyting works like a charm and I really like your extension model. Good work boys! Thats why I wasn't sure. If I do it correctly. |
If I understand this issue correctly, it is a super-set of #618 - is this correct? I see in the stackoverflow issue you requested for us to write our use case - well, here's mine: I am intending to use this functionality to take a screenshot of the GUI and save them so that test failures are accompanied by screenshots (see TestFX/TestFX#306 for more details). Thanks. I hope I am understanding the state of things correctly. |
Do I understand it right that for now to get test result state I have to use AfterTestExecutionCallback ?. Then from within implemented method I can take
Are there any plans to implement this feature? As for question
#618 is about TestExecutionListener which is not accessible from within extensions |
I'm adding this issue to 5.1 Backlog. That means that we will reconsider it when we go over our 5.1 backlog. The current focus, however, is to finish the first GA version. |
Any additional word on this? It would be super useful. Currently we have JUnit rules for some tests that evaluate not only the test result but also some custom timing data and report that to an external service. Using an engine listener wouldn’t work for us since we would need to get access to the timing data which would be stored in an extension store. |
Also, a reactive version that allows for an alteration of the TestPlan sounds very interesting for things like automatically retrying certain tests only on failures, etc. |
@marcphilipp There is any news about this feature? |
@littleclay You can publish the timing data from your extension using
It does, but I think it may be a different extension point as pointed out by @sormuras in #542 (comment).
@TpSr52 No, unfortunately not. While we're not opposed to adding such an extension point, we haven't had time to work on it so far. It would help if someone submitted a pull request for a |
It would be useful if this feature is added to the extension framework, we have a need to check when a Test is failed and do certain actions on the same |
This does sound quite fun to take a look at (up-for-grabs 😎 ) However, it is still not completely clear to me what you're trying to achieve that TestExecutionListener.executionFinished doesnt already do. If it's about the store, i personally use an external map in my listener class, by uniqueID @deepakab03 , @bugs84 care to explain please? |
@geo-m @nicolaiparlog I tried to use a TestExecutionListener to get the result info into my CustomExtension, but for me it didn't work because of the order of the calls:
I can't use any info collected in executionFinished because its collected after the extension methods are called where I actually need to use the info. |
Voting for the initial request. @AfterEach
public void finishTestCase(TestExecutionResult result) {
try {
ExtentManager.createScreenShot(driver.get());
LOGGER.debug("Finishing test... " + result.getName());
switch (result.getStatus()) {
case FAILURE:
ExtentManager.getCurrentReporter().get().log(
Status.FAIL,
Utils.prettyReport(result.getThrowable().toString()),
ExtentManager.buildScreenshotMedia(result.getName()));
break;
case SKIP:
ExtentManager.getCurrentReporter().get().skip(result.getThrowable().toString());
break;
case SUCCESS:
ExtentManager.getCurrentReporter().get().info(
"Last Screen of the test",
ExtentManager.buildScreenshotMedia(result.getName()));
break;
}
} finally {
LOGGER.debug("Closing Browser...");
driver.get().quit();
} where |
Prior to this commit, the log message generated for exceptions thrown by a TestWatcher callback method was specific to @test methods. However, since @testfactory methods and @testtemplate methods (e.g., @RepeatedTest and @ParameterizedTest) are supported by the same infrastructure, the log message was misleading in such cases. This commit improves the log message by including the display name as well. This helps to discern between individual invocations of repeated tests, dynamic tests, parameterized tests, etc. Issue: #542
This commit disables TestWatcher support for @testfactory methods, since such methods are actually containers, and the TestWatcher API currently does not support containers. Issue: #542
Overview
Some functionality written in JUnit 4 is based on the usage of Rules.
There a custom rule is used to send test results to an external system - where they can be seen later.
The
TestWatcher
Rule API in JUnit 4 provides me with the following three callback methods:protected void succeeded(Description desc);
protected void failed(Throwable e, Description desc);
protected void skipped(AssumptionViolatedException e, Description desc);
This enables me to be notified what the test result is -- failed, success, or skipped -- (
AssumptionViolatedException
exception is thrown during test execution).@mmerdes has done a good job of adapting existing JUnit 4 rules to extensions in JUnit Jupiter,
but this "migration support" unfortunately does support method result callbacks.
I've researched this topic and came to realize that for now there is no straight reliable way to implement this feature using only JUnit Jupiter's extension model.
The closest extension is
AfterTestExecutionCallback
, but its callback methodafterTestExecution(ExtensionContext)
does not provide the necessary information (i.e., the test execution result).So you can't tell for sure if the test succeeded, failed, or was aborted/skipped. Indirect ways to solve this problem do not look reliable.
Proposal
One possible solution is to introduce a new
Extension
API (e.g.,TestFinished
) that receives the test execution result via its callback method.Each extension that implements the
TestFinished
interface will get notified of the test execution result.The text was updated successfully, but these errors were encountered: