-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
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
Add dynamic container support in @TestFactory methods #813
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this looks great overall! 👍
The fact that this did not require any changes outside of Jupiter tells me that our abstractions work, even though Node.isLeaf()
feels a bit fishy.
return new DynamicContainer(displayName, StreamSupport.stream(dynamicNodes.spliterator(), false)); | ||
} | ||
|
||
public static DynamicContainer dynamicContainer(String displayName, Stream<? extends DynamicNode> dynamicNodes) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm wondering if we should make them use Supplier<Iterable<? extends DynamicNode>>
/Supplier<Stream<? extends DynamicNode>>
. Thoughts?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Every overload that makes usage of dynamicContainer
more elegant is good to have.
private final DynamicContainer dynamicContainer; | ||
private final AtomicInteger index; | ||
|
||
DynamicContainerTestDescriptor(UniqueId uniqueId, DynamicContainer dynamicContainer, AtomicInteger index, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AtomicInteger
is mutable. I think we should pass the index as an int
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Never mind, if we follow my proposal below we don't need to pass the index at all.
public JupiterEngineExecutionContext execute(JupiterEngineExecutionContext context, | ||
DynamicTestExecutor dynamicTestExecutor) throws Exception { | ||
TestSource source = getSource().orElseThrow(AssertionError::new); | ||
for (DynamicNode childNode : dynamicContainer.getDynamicNodes()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think every level of the hierarchy should have separate indices starting with 1 on every level.
@@ -71,11 +74,13 @@ protected void invokeTestMethod(JupiterEngineExecutionContext context, DynamicTe | |||
Object instance = testExtensionContext.getTestInstance(); | |||
Object testFactoryMethodResult = executableInvoker.invoke(getTestMethod(), instance, testExtensionContext, | |||
context.getExtensionRegistry()); | |||
|
|||
try (Stream<DynamicTest> dynamicTestStream = toDynamicTestStream(testFactoryMethodResult)) { | |||
TestSource source = getSource().orElseThrow(AssertionError::new); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know this "cannot happen", but I'd be a little more comfortable with JUnitException::new
.
descriptor = new DynamicTestTestDescriptor(uniqueId, test, source); | ||
} | ||
else { | ||
DynamicContainer container = (DynamicContainer) node; // ClassCastException is an error. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need this comment?
return nodes; | ||
} | ||
|
||
@TestFactory |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this is the best example for the documentation. I'd rather show some real nesting. Thoughts?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure. Any real example available?
@marcphilipp wrote:
👍 |
Since I opened #604, @sormuras asked me to comment on this PR. Regarding the hierarchical organization of tests, I think it fits the bill very well. 👍 The other part of #604 is that it talks about an extension point for dynamic tests (like in #371) but the discussion regarding that can happen elsewhere. |
Prior to this commit only a flat collection of dynamically generated tests was allowed as the return type of a @testfactory annotated method. The collection entry type was set to `DynamicTest`. This commit introduces the abstract base class `DynamicNode` and a `DynamicContainer` class collecting node instance. @testfactory annotated methods are now allowed to return a collection of nodes -- which can be a test or a named container of tests. Creating a dynamic tree of tests like that gives users the ability to better structure the generated tests. The old behaviour, returning only instances of `DynamicTest`, is preserved.
Team decision: Merge this feature "as-is" and move the open documentation tasks into a new issue. |
Overview
Addresses #695 and #604
Add dynamic container support in @testfactory methods.
https://travis-ci.org/junit-team/junit5/builds/228235319#L596 is generated by:
I hereby agree to the terms of the JUnit Contributor License Agreement.
Definition of Done