-
-
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
Introduce junit-platform-suite-engine #2416
Introduce junit-platform-suite-engine #2416
Conversation
This implementation is not done yet. However before continuing it would be good to give this a review to ensure that this is fundamentally the right way to go. Currently this PR features:
ImplementationThe suite engine converts an annotated class into a discovery request. This request is executed and the resulting test plan is mapped to a tree of test descriptors. In essence the tree of test descriptors are a view on the test plan. So suppose the discovery requests produces this test plan:
Then that test plan is mapped to a tree of test descriptors like so:
The unique identifiers are remapped by pre-pending the unique identifier of the suite. So:
When resolving tests by unique id this is reversed. Known limitations
I don't think these limitations are insurmountable, however I would consider solving them out of scope for this PR. |
d2c8982
to
04e7397
Compare
Codecov Report
@@ Coverage Diff @@
## main #2416 +/- ##
============================================
+ Coverage 90.55% 90.57% +0.02%
- Complexity 4718 4791 +73
============================================
Files 413 423 +10
Lines 11665 11865 +200
Branches 921 922 +1
============================================
+ Hits 10563 10747 +184
- Misses 825 834 +9
- Partials 277 284 +7
Continue to review full report at Codecov.
|
45c13bb
to
3abe7c4
Compare
So @marcphilipp what do you think? If there are general aspects you have doubts about -more a problem with the concept of a suite engine, rather then this particular implementation- I'd like to hear that too. I did create a small demo to play around with: |
For reference, this technique of a "meta TestEngine" (that recursively calls other engines using the launcher API) was also a feature of the |
Good to know that the idea has already been tested! Any practical problems you've ran into with regards to IDEs and other bits of tooling?
Unless I'm misunderstanding the purpose and function of The line |
There are bits of the code in various places that softly assume that the Engine will be at the top of the hierarchy. For example, the naming convention for the segments of the UniqueId for the tests. In our hierarchy, the BundleEngine's segment uses "engine:bnd-bundle-engine" and the sub-engines have "sub-engine:junit-jupiter", etc. But these assumptions seem to be "soft" and can be worked around. We've been using the
On the contrary, it seems you've understood the purpose and function well. 😄 Sorry, I used the terms "recursive" and "launcher API" a bit too loosely. By "recursive" I meant one |
@mpkorstanje Sorry for the delay! This is still on my list, just haven't had the time to do a proper review, yet. |
I haven’t checked the implementation so maybe this has already been discussed: How are the engines called from this one being prevented from running their tests? If they are not the tests in the suite will be run twice, right? |
They are not. Currently to avoid this the suite engine and all other engines that are not part of the suite should be explicitly excluded in the discovery request. While perhaps unexpected I don't think we can implement a less surprising default behavior. Did you have anything in mind? Edit: included -> excluded |
I think the problem occurs when you run all tests (from IDE or Gradle or Maven) since then we'd see some tests being executed twice. Maybe a reasonable default behaviour would be to NOT execute a suite at all when the request includes other test engines? |
I'm not sure if that would be reasonable.
|
@mpkorstanje Great work, looking forward to this so I can migrate to |
...platform-suite-engine/src/main/java/org/junit/platform/suite/engine/SuiteTestDescriptor.java
Outdated
Show resolved
Hide resolved
Hi, Are there any updates on this? What still needs to be done/tested? Is there any ETA on when this could be accepted, merged and released? Kind regards, Martin |
@carlspring Still on my list and not forgotten, just a little short on time these days. Will try to get it in for 5.8 M1, can't promise any date, though. |
Hi @marcphilipp , Thanks for your quick response! Would you mind clarifying what still needs to be done and how much of an effort it would be? Also, just off the record and quite optimistically, when do you suppose Thanks again! :) |
I think the first two posts of this MR should answer that. If that leaves you with any questions you can build this locally and try it out. If you are looking to contribute the User Guide and Release notes have not been updated yet. I was waiting for Marcs review before writing these but in the mean time I'd welcome a PR too. Please also feel free to give the implementation a review. |
Implements a test engine that allows declarative execution of test suites using the `@Suite` annotation. Internally the Suite Engine uses the JUnit Platform Launcher. The engine works by mapping the `TestIdentifier` used by the launcher to `TestDescriptor` used by the engine during discovery and execution. ``` package org.junit.platform.suite; import org.junit.platform.suite.api.SelectPackages; @suite @SelectPackages("org.junit.suite.testcases") class SelectPackageSuite { } ``` Is equivalent to: ``` import org.junit.platform.engine.discovery.DiscoverySelectors; import org.junit.platform.launcher.Launcher; import org.junit.platform.launcher.LauncherDiscoveryRequest; import org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder; import org.junit.platform.launcher.core.LauncherFactory; public class Main { public static void main(String[] args) { Launcher launcher = LauncherFactory.create(); LauncherDiscoveryRequest request = LauncherDiscoveryRequestBuilder.request() .selectors(DiscoverySelectors.selectPackage("org.junit.suite.testcases")) .build(); launcher.execute(request); } } ``` The suite engine converts an annotated class into a discovery request. This request is executed and the resulting test plan is mapped to a tree of test descriptors. In essence the tree of test descriptors are a view on the test plan. So suppose the discovery requests produces this test plan: ``` JUnit Jupiter |- TestA ||- method1 ||- method2 |- TestB ||- method1 ||- method2 ``` Then that test plan is mapped to a tree of test descriptors like so: ``` SuiteEngine |- ExampleSuite ||-JUnit Jupiter |||- TestA ||||- method1 ||||- method2 |||- TestB ||||- method1 ||||- method2 ```` The unique identifiers are remapped by pre-pending the unique identifier of the suite. So: ``` junit-jupiter/TestA/method1() -> junit-suite/ExampleSuite/junit-jupiter/TestA/method1() ``` Issue: junit-team#744
…uite/engine/SuiteLauncher.java Co-authored-by: Marc Philipp <marc@gradle.com>
8fe44a2
to
4ade1c4
Compare
Cheers. Looking forward. |
Btw. Should I squash all commits before they're merged? |
...rm-suite-engine/src/main/java/org/junit/platform/suite/engine/DiscoverySelectorResolver.java
Outdated
Show resolved
Hide resolved
Don't bother, I'll do that when merging. |
Thanks so much for all the hard work, @mpkorstanje! 👍 I sent a tweet from the team account in your honor. https://twitter.com/junitteam/status/1359130553224749059 |
You're welcome. This was fun to do. |
@mpkorstanje thanks for your work. Now that this PR is merged, could you update the answer here? https://stackoverflow.com/questions/64587739/cucumberoptions-in-cucumber-junit-platform-engine/64598725#64598725 |
No, not any time soon, but feel free to post another answer. |
Implements a test engine that allows declarative execution of test suites using the `@Suite` annotation. Internally the Suite Engine uses the JUnit Platform Launcher. The engine works adding the test descriptors of the discovered engines and tests as children to its own test descriptor. ```java package org.junit.platform.suite; import org.junit.platform.suite.api.SelectPackages; @suite @SelectPackages("org.junit.suite.testcases") class SelectPackageSuite { } ``` Is equivalent to: ```java import org.junit.platform.engine.discovery.DiscoverySelectors; import org.junit.platform.launcher.Launcher; import org.junit.platform.launcher.LauncherDiscoveryRequest; import org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder; import org.junit.platform.launcher.core.LauncherFactory; public class Main { public static void main(String[] args) { Launcher launcher = LauncherFactory.create(); LauncherDiscoveryRequest request = LauncherDiscoveryRequestBuilder.request() .selectors(DiscoverySelectors.selectPackage("org.junit.suite.testcases")) .build(); launcher.execute(request); } } ``` Resolves junit-team#744.
Overview
Implements a test engine that allows declarative execution of test suites using
the
@Suite
annotation.Internally the Suite Engine uses the JUnit Platform Launcher. The engine works
adding the test descriptors of the discovered engines and tests as children to its
own test descriptor.
Is equivalent to:
Issue: #744
I hereby agree to the terms of the JUnit Contributor License Agreement.
Definition of Done
@API
annotations