-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
-
-
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
Enhance support for dynamic tests #378
Comments
I think it could also be useful/interesting for extensions in this case to do be able to compute "test matrix" by using multiple different parameter resolver extensions and different declarative parameterized values. For example: @Test
@ForAValue({3, 4})
@ForBValue({5, 6})
void runMyTest(AClass aValue, BClass bValue) { ... } I would like to have the ability to have an extension that can register additional tests by looking at the context of a method or class. |
Regarding lifecycle integration for dynamic tests... What exactly should that look like? Would the whole extension shebang (test instance processing, test parameter injection, before/after, ...) be run for test factory methods and then again for each individual dynamic test? Mmmh, now that I'm writing this I don't actually see a problem with that anymore. But I'm sure I saw one when creating #530... Damn brain! 😫 |
That's certainly what I have in mind! |
Here is a proposition for lifecycle hooks invocations around dynamic tests : #735 |
We just stumbled across this issue because we need the test-lifecycle for dynamic tests. We also thought about using test templates instead, but we need the test instance variables (here wired via Spring) to actually retrieve the test parameters. So our factory method looks something like this: @ExtendWith(SpringExtension.class)
class SpringTest {
@Autowired
private List<Bean> beans;
@ExtendWith(MyExtension.class)
@TestFactory
Stream<DynamicTest> cmTeasableTests() {
return beans.stream().map(b -> dynamicTest("display name", () -> doTestFor(b)));
}
} So unless we find a solution how to access instance level fields from test-templates the test factory is much more convenient to use - but misses the important test lifecycle. |
Why don't you implement |
This is what I do as workaround now. But it does not fit to the extension mechanism. So what I do now is to manually create for example after each and handleTestExecutionException by using try-catch-finally. But my impression is, that this is not the expected behavior. It took my a bunch of time to realize that my tests failed, because the cleanup (in after each) was only done when all dynamic tests are done. |
For me Dynamic Tests are handled far to stepmotherly. I'd love to:
|
Dynamic tests are just grouped assertions that show up in the test plan. Think of them as Most of your requested features are already provided by normal or parameterized tests. If those two don't fit your need maybe we can extend them? Perhaps you want and need to roll your own TestTemplate implementation? |
What's keeping you from doing that? Are you just saying you want to access Spring beans from within a custom test template implementation? If so, that's already possible. |
That's unfortunately not possible in Java with Java's standard reflection APIs, and any attempt to support such annotation lookups would rely on lambda expression implementation details that may change in future JDK releases. |
However, if you're curious about some hacky way to achieve that, feel free to take a look at my serialized lambda PoC here: sbrannen/junit-lambda-playground@ef38dde |
I am sad to say that the "serialized lambda" technique no longer works. See the following JDK issues for details. It is therefore not possible to perform parameter resolution based on annotations. Thanks to @nicolaiparlog for bringing this to my attention. |
@mmichaelis, this answer I posted on StackOverflow shows how to parameterize tests from Spring beans: https://stackoverflow.com/a/56769619/388980 If you go that route, you have proper test lifecycle method support for each parameterized test invocation. |
Would it be possible to just "redefine" // Virtual part start
@ParameterizedTest
@MethodSource
void testDynamicStuff(DynamicTest test) {
test.getExecutable().execute();
}
// Virtual part end
// @TestFactory
Stream<DynamicTest> testDynamicStuff() {
return ...;
} or at least a new annotation that behaves like this? |
Not really since dynamic tests can be nested. |
Hi Tibor, I was working with JUnit 5, creating dynamic tests, when I run the build using maven, But in the Console logs still lists with indexes, and the test case Displayname is not printed. I have the below Plugin config: <plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>${maven-surefire-plugin.version}</version>
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>${junit-jupiter.version}</version>
</dependency>
<dependency>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
<version>${junit-vintage.version}</version>
</dependency>
</dependencies>
<configuration>
<statelessTestsetReporter implementation="org.apache.maven.plugin.surefire.extensions.junit5.JUnit5Xml30StatelessReporter">
<usePhrasedFileName>false</usePhrasedFileName>
<usePhrasedTestSuiteClassName>true</usePhrasedTestSuiteClassName>
<usePhrasedTestCaseClassName>true</usePhrasedTestCaseClassName>
<usePhrasedTestCaseMethodName>true</usePhrasedTestCaseMethodName>
</statelessTestsetReporter>
<consoleOutputReporter implementation="org.apache.maven.plugin.surefire.extensions.junit5.JUnit5ConsoleOutputReporter">
<usePhrasedFileName>false</usePhrasedFileName>
</consoleOutputReporter>
<statelessTestsetInfoReporter implementation="org.apache.maven.plugin.surefire.extensions.junit5.JUnit5StatelessTestsetInfoReporter">
<usePhrasedFileName>false</usePhrasedFileName>
<usePhrasedClassNameInRunning>true</usePhrasedClassNameInRunning>
<usePhrasedClassNameInTestCaseSummary>true</usePhrasedClassNameInTestCaseSummary>
</statelessTestsetInfoReporter>
</configuration>
</plugin>
Please help me out on this scenario |
@arun-mano Please report this issue to the Maven Surefire project. |
I wrote an extension that supports Maybe it would be an idea to leave the current lifecycle as it is and add these annotations instead? |
That's another option; however, it would not allow individual dynamic tests to benefit from extensions that provide additional behavior via the standard lifecycle callbacks. |
Yes. So dynamic tests are either 'testlets' or have a fully fledged test lifecycles. I'm fine with both options. |
As dynamic tests are functional, would a functional approach be more suitable and more flexible instead of trying to hook into the existing lifecycle & annotations? E.g.
This has the flexibility of being arbitrarily applicable, e.g. to a DynamicContainer:
This is especially useful if something needs to be performed before or after a group of tests, rather than all tests or each test. I've not found a way to do this other than counting down how many tests have been executed and executing some code when we reach 0. It can also work to an arbitrary depth of nesting. |
I like that approach, but for the container it must be clear, whether the before will be |
Having thought about it, I would argue that one doesn't need the concept of all/each in this context. It is always before or after whatever container/node you added it to. This is equivalent to a
is misleading (as there's only one test). And to do the equivalent of a
|
@Druckles Just to confirm, is your api call stored in a new field or is it used to mutate the test instance?
If it's only syntactic sugar, I don't see a reason, why I should call |
Just a hint: I found |
There seems to be bugs in org.junit.jupiter.api.BeforeEach of JUnit 5 at this moment. It cannot guarantee the annotated method being excuted before each test method. References: - junit-team/junit5#2360 - junit-team/junit5#378
Status Quo
Since 5.0 M1, dynamic tests can be registered as lambda expressions, but there are a few limitations with the current feature set.
Topics
TestReporter
.Related Issues
"Introduce support for parameterized tests""Improve documentation of DynamicTest lifecycle""TestReporter does not capture the correct TestIdentifier when used with DynamicTests"Deliverables
Address each topic.
The text was updated successfully, but these errors were encountered: