TNG / ArchUnit

A Java architecture test library, to specify and assert architecture rules in plain Java
http://archunit.org
Apache License 2.0
3.13k stars 284 forks source link

Performance: archunit-junit5 may scan complete JDK for `@ArchTest` #1316

Open rweisleder opened 1 month ago

rweisleder commented 1 month ago

Context

I'm currently developing a library with common ArchUnit rules. To test them, I evaluate them against different classpaths. Therefor I created a multi-module Maven project:

my-project
+--- my-rules
+--- tests-with-classpath1
+--- tests-with-classpath2
`--- tests-with-classpath3

The module my-rules contains my rules in src/main/java. The other modules have a dependency on my-rules and dependencies for test, but no src folder.

Description

In IntelliJ, when I select the module "tests-with-classpath1" and execute "Run 'All Tests'", the ArchUnitTestEngine tries to discover tests in the complete classpath, even in the JDK.

It's because IntelliJ calls the registered TestEngines with DiscoverySelectors.selectPackage(""). However, if at least one class is present in the module, IntelliJ uses the ClasspathRootSelector. (The different selectors look inconsistent, which may be a cause of a bug/missing feature in IntelliJ: IDEA-354486)

With the PackageSelector [packageName = ''], the ArchUnitTestEngine now scans the complete classpath including the JDK. On my machine, it takes about 30 seconds to discover all tests until the first gets executed.

The behavior and implementation of ArchUnitTestEngine looks plausible, but I would be positively surprised about any @ArchTest inside the JDK. I suggest to replace the implementation with org.junit.platform.commons.support.ReflectionSupport#findAllClassesInPackage which somehow does not scan the JDK.

Reproducer

I created an example to reproduce the issue: https://github.com/rweisleder/demo-test-engine