-
Notifications
You must be signed in to change notification settings - Fork 297
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
run tests with JUnit Platform #1294
Merged
Merged
Conversation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
I've compared the Gradle test xml report of all the executed tests before and after. |
hankem
approved these changes
Jun 1, 2024
archunit/src/test/java/com/tngtech/archunit/testutil/OutsideOfClassPathRule.java
Outdated
Show resolved
Hide resolved
codecholeric
force-pushed
the
migrate-to-junit-5
branch
from
June 9, 2024 20:49
105bc09
to
c649f41
Compare
We should make sure we always configure `useJUnit {..}`, even if the property `example` is not set. Right now this doesn't make a difference, but when we switch to JUnit 5 this module still needs to use JUnit 4. Signed-off-by: Peter Gafert <[email protected]>
codecholeric
force-pushed
the
migrate-to-junit-5
branch
from
June 9, 2024 21:28
c649f41
to
6c53da9
Compare
It has always been a little brittle to use classes that were compiled regularly and reachable from the default ClassLoader for test "outside the classpath". The reason is that if such a class is referenced at any point before the test runs, then the class is already loaded. And then we can move these classes out of the folder in the file system later on all we want, the ClassLoader can still load them (this was also the reason why we had to use strings for the class names in such tests instead of referencing the `Class` objects). I found out that switching to JUnit 5 this actually becomes a problem, because something in the build infrastructure seems to trigger a class loading of all classes before already with the test ClassLoader (maybe it's scanning classes for annotations and by that triggering class loading). To make the test infrastructure more robust we now don't use regularly compiled classes out of the URL classpath of the ClassLoader, but instead we keep the source files as resources and compile them dynamically when needed. This way we can be sure that the regular test ClassLoader has no chance to ever know these classes ahead of being used by a test. And it also has no chance to load these classes anywhere from the regular classpath. Signed-off-by: Peter Gafert <[email protected]>
When migrating to JUnit Platform I noticed tests obscurely failing with symptoms like "ClassNotFoundException" where they worked fine before. The reason seems to be ``` LocationsTest.locations_of_packages_from_custom_ClassLoader_for_JARs_with_directory_entries ``` Or more specifically the line ``` Thread.currentThread().setContextClassLoader(new URLClassLoader(new URL[]{jarUrl}, null)); ``` Since that test doesn't call `independentClasspathRule.configureClasspath()` the internal `setup` is `null`, and restoration of the context `ClassLoader` only happens if the `setup` is not null. Thus, this test pollutes the context `ClassLoader` for tests to come, which seems to have caused the issues then (in particular resolving missing classes via `ClassResolverFromClasspath` looks at the context `ClassLoader` and can then suddenly not load the expected classes). It seems like when running with JUnit 4 support the context `ClassLoader` was somehow restored to the `AppClassLoader` which isn't the case anymore with JUnit Platform support. To make this more foolproof we will now simply always restore the context `ClassLoader` when `IndependentClasspathRule` is used. Signed-off-by: Peter Gafert <[email protected]>
To pave the way to migrate to JUnit 5 we now switch the build to use the JUnit Platform runner by switching to `useJUnitPlatform {..}` in our Gradle build files. This doesn't effectively change much on the surface, because we still keep all JUnit 4 annotations and test infrastructure. But it now runs our JUnit 4 tests using the JUnit Vintage Engine via the Gradle JUnit Platform integration, instead of directly through the Gradle JUnit 4 integration. This effectively allows us to combine JUnit 4 and JUnit 5 tests in the same Gradle module since we can combine any number of JUnit Platform test engines. We include both JUnit Vintage and JUnit Jupiter engine, so it will pick up JUnit 4 tests as well as JUnit 5 tests. Then we can migrate tests to JUnit 5 at any pace and any granularity that we want. Note that within `archunit-integration-test` the situation is a little tricky, because we include both `archunit-junit4` and `archunit-junit5`. And those share some annotations, but with different effect. For example, `@AnalyzeClasses` alone triggers the `archunit-junit5-engine` to run a test class. If it's also annotated with `@RunWith(ArchUnitRunner.class)`, then the JUnit Vintage Engine will pick it up and run it as a JUnit 4 test. Thus, I noticed that the tests also annotated with `@RunWith(ArchUnitRunner.class)` are run twice there. Since this is an irrelevant corner case for real life scenarios, I've simply removed the `@RunWith`, because we want to run our tests with `archunit-junit5` anyway. I've compared the Gradle test xml report of all the executed tests before and after. From what I see the output coincides for both standard and slow tests (except for one wrongfully executed slow test in `archunit-junit` before the change, but this is then no problem but instead fixed now). Signed-off-by: Peter Gafert <[email protected]>
by removing some dependencies that were probably unsued since introduced with 230a2f4 Signed-off-by: Manfred Hanke <[email protected]>
To provide an SLF4J implementation to all tests, `dependency.log4j_slf4j` (with the implementation of `org.apache.logging.slf4j.SLF4JServiceProvider` picked up at runtime by the ServiceLoader) is moved to the `archunit.java-testing-conventions` plugin. It transitively depends on `dependency.log4j_core` / `dependency.log4j_api`, which are only needed as explicit implementation dependencies in modules that specifically test logs. Signed-off-by: Manfred Hanke <[email protected]>
codecholeric
force-pushed
the
migrate-to-junit-5
branch
from
June 9, 2024 21:37
6c53da9
to
320e3dc
Compare
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
To pave the way to migrate to JUnit 5 we now switch the build to use the JUnit Platform runner
by switching to
useJUnitPlatform {..}
in our Gradle build files.This doesn't effectively change much on the surface, because we still keep all JUnit 4 annotations and test infrastructure.
But it now runs our JUnit 4 tests using the JUnit Vintage Engine via the Gradle JUnit Platform integration,
instead of directly through the Gradle JUnit 4 integration.
This effectively allows us to combine JUnit 4 and JUnit 5 tests in the same Gradle module
since we can combine any number of JUnit Platform test engines.
We include both JUnit Vintage and JUnit Jupiter engine, so it will pick up JUnit 4 tests as well as JUnit 5 tests.
Then we can migrate tests to JUnit 5 at any pace and any granularity that we want.