Skip to content
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

Invoke lifecycle hooks around each dynamic test #735

Closed
wants to merge 1 commit into from
Closed

Invoke lifecycle hooks around each dynamic test #735

wants to merge 1 commit into from

Conversation

ledoyen
Copy link
Contributor

@ledoyen ledoyen commented Mar 13, 2017

Overview

@BeforeEach, @AfterEach and associated callback extensions run once around @TestFactory methods.

The proposition here is to run these hooks around each dynamic tests created by the factory method.

Hooks are not invoked around the factory method, because it is a container and type (container or test) cannot be determined from a hook implementation.


I hereby agree to the terms of the JUnit Contributor License Agreement.

Copy link
Member

@sbrannen sbrannen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For a commit that changes so much in the fundamental execution of tests, we will require (in the commit message) a more detailed analysis of the status quo, the impetus for change, and why each decision was made.

}

protected void invokeBetweenBeforeAndAfter(JupiterEngineExecutionContext context,
Consumer<JupiterEngineExecutionContext> action) {
ThrowableCollector throwableCollector = context.getThrowableCollector();

// @formatter:off
invokeBeforeEachCallbacks(context);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please don't mess with the indentation art.

In other words, please retain the original indentation so that diffs are easier to follow.

return context;
}

protected void invokeBetweenBeforeAndAfter(JupiterEngineExecutionContext context,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't like this method name: it does not align nicely with the existing methods in that class.

Something like invokeTest() or executeTest() would make more sense here.

}

protected void invokeBetweenBeforeAndAfter(JupiterEngineExecutionContext context,
Consumer<JupiterEngineExecutionContext> action) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The term action here is insufficient to convey its purpose.

Something like testInvoker or testExecutor would be more suitable.

@@ -69,6 +70,18 @@ public boolean isLeaf() {
}

@Override
public JupiterEngineExecutionContext execute(JupiterEngineExecutionContext context,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please explain in great detail the need to override the execute() method, not only here but also in the commit message.

Copy link
Contributor Author

@ledoyen ledoyen Mar 15, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I choose to override the execute() method here to prevent calls to before and after hooks around a container execution.
This is because a hook implementation can not know on which (of a container or a test) it is executed.
I assumed that @BeforeEach meant before each test, in this particular case, unlike what's said in the annotations javadoc.

A cleaner way can be to declare a new annotation @BeforeEachTest and let callback implementations know about the type of test (container or not).

If this is something you prefer, I can give it a try.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unless I'm mistaken, lifecycle callbacks currently apply to @TestFactory methods.

So it appears that you have removed this functionality, which some people may depend on.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At the moment, no, I don't think we want to introduce any additional lifecycle annotations.

Copy link
Contributor Author

@ledoyen ledoyen Mar 16, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you think about invoking lifecycle callbacks around @TestFactory methods and around each dynamic tests and making implementations aware of the type (container or test) they are invoked on ?
This could be done by adding an isContainer:boolean method to the TestExtensionContext like on the TestDescriptor interface.

I tried to improve the MockitoExtension by adding a reset of mocked field / parameters in Store before each test.
This is why I removed callback invocation around @TestFactory methods in favor of dynamic tests in the first place.

@sbrannen
Copy link
Member

Thanks for the PR! 👍

I only had a few minutes to briefly review it within the browser. So if my review comments are vague, please ask for clarification.

@sormuras sormuras added this to the 5.0 M5 milestone Mar 14, 2017
@sbrannen
Copy link
Member

I have some serious concerns about management of the JupiterEngineExecutionContext.

Specifically:

What happens if a dynamic test results in a failure (i.e., exception thrown)? Does the ThrowableCollector get reset?

What happens if an extension stores state in the ExtensionContext.Store? Does the Store get cleared before the next dynamic test is executed?

In general, in JUnit Jupiter it is required that each execution of a node in the test tree gets a new execution context.

So without explicit tests in place that confirm proper behavior for the above requirement, we will not be able to merge this PR.

@ledoyen
Copy link
Contributor Author

ledoyen commented Mar 15, 2017

I understand.

To answer to these questions and provide a solution, can you tell be me if dynamic tests are supposed to be executable in parallel (as the executor is stream-based).

I was not able to find in the user guide or in the javadoc, if there is any concerns about parallelism and how this should be handled in TestDescriptors.

@sbrannen
Copy link
Member

sbrannen commented Mar 15, 2017

To answer to these questions and provide a solution, can you tell be me if dynamic tests are supposed to be executable in parallel (as the executor is stream-based).

At the moment, no.

There is currently zero support for parallel test execution with JUnit Jupiter. See #60.

So, please do not add any support related to parallel test execution in conjunction with this PR.

@ledoyen
Copy link
Contributor Author

ledoyen commented Apr 8, 2017

It's been a while since I have time to spend on this.

After considerations, it may not be such a good idea to try micro-management around DynamicTests.
GIven the other issues pointed-out in #378 , I think I will focus on the use @TestTemplate.

I suggest that we close this PR if that is ok with you.

@marcphilipp
Copy link
Member

Sure, thanks for getting back to us!

@marcphilipp marcphilipp closed this Apr 8, 2017
@sbrannen sbrannen removed this from the 5.0 M5 milestone May 7, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants