Hi All! In the JDK 9 module environment running unit tests is more complex task than it was in the classpath mode. The problems of test compilation and execution are nicely described in the following thread http://mail.openjdk.java.net/pipermail/jigsaw-dev/2016-March/thread.html#6587 on the jigsaw-dev mailing list. Also there is lots of different test scenarios as described in http://mail.openjdk.java.net/pipermail/jigsaw-dev/2016-March/007152.html.
Basically there are two problems: The first problem is that modules enforce module boundaries, only exported packages are seen from other modules. The second problem is the module readability - dependency among modules. The tests can be executed in the following ways: 1st) In classpath mode - the current way JunitTask executes tests All the libraries, project artifacts, junit and test classes are on classpath. In this scenario the classpath artifacts become a part of the unnamed module. There is no problem with module boundaries or readability as all artifacts are a part of a single module (unnamed module). However the tests do not run in the same environment as the product which executes the project in its own module. Also services registered in the module-infos are not available in the ServiceLoader. This is probably not acceptable. 2nd) Blackbox testing. The tests have its own module, in other words there is a module-info in the test sources in addition to module-info in sources. All the libraries, project artifact, test classes and junit are on modulepath. The test’s module-info requires the project module (sources) and junit end exports all test packages to make them accessible by junit. The limitation is that in such a setup only classes exported by the project module can be tested (unless -XaddExports:sourceModule/sourcePackage=testModule is passed to the JVM). The -addmods:testModule JVM option is needed to make testModule active and readable by junit. Next limitation is that the test classes cannot be in the same packages as tested sources because split packages are not supported by the module system. The module readability graph: http://wiki.netbeans.org/wiki/images/a/a9/Blackbox_module_path.png The complete java command line is: java -mp build/test/classes:build/classes/:lib/lib.jar:lib/junit.jar -addmods:testModule -m junit/org.junit.runner.JUnitCore app.AppTest 3rd) Whitebox testing - probably most common The tests are inlined into the source module. All the libraries, project artifact, test classes and junit are on modulepath (there is an option to keep junit on classpath which I will explain later). As the test classes are in the same module as project sources there is no problem with module boundaries and readability among project sources and tests. The test packages need to be exported to be accessible by junit by -XaddExports:sourceModule/testPackage=junit and made readable by JUnit -XaddReads:sourceModule=junit -addmods sourceModule. The module readability graph: http://wiki.netbeans.org/wiki/images/c/ca/Whitebox_module_path.png The complete java command line is: java -mp build/classes/:lib/lib.jar:lib/junit.jar -Xpatch:sourceModule=build/test/classes -addmods sourceModule -XaddExports:sourceModule/testPackage=junit -XaddReads:sourceModule=junit -m junit/org.junit.runner.JUnitCore app.AppTest There is also a possibility to keep the junit.jar on the classpath rather than on the modulepath. In this case junit becomes a part of an unnamed module, when on modulepath it becomes an automatic module. The same JVM options are required, only the -XaddReads:sourceModule=junit changes to -XaddReads:sourceModule=ALL-UNNAMED. The disadvantage of this solution is that unit test can read the unnamed module which contains junit but may contain other unwanted jar files on classpath. The only advantage of these solution is that it does not need module execution (-m JVM option). The module readability graph: http://wiki.netbeans.org/wiki/images/3/38/Whitebox_class_path.png The complete java command line is: java -mp build/classes/:lib/lib.jar -cp lib/junit.jar -Xpatch:sourceModule=build/test/classes -addmods sourceModule -XaddExports:sourceModule/testPackage=junit -XaddReads:sourceModule=ALL-UNNAMED org.junit.runner.JUnitCore app.AppTest The JUnit task needs to be extended to support all three scenarios. There are two possibilities how to extend the JUnitTask: 1st) Minimal needed changes Just add a modulepath to JUnit task. When junit library is not found on the classpath but found on the module path do the modular execution by -m junit/<mainclz> rather than classpath execution. The user is responsible for passing the -XPatch, -XaddExports, -XaddReads, -addmods JVM options. Options like -XaddExports are harder to calculate as they require list of test packages. But it can be done by the following pathconvert: <dirset id="packages" dir="build/test/classes" includes="*"/> <pathconvert refid="packages" property=“exports.cmd” pathsep=" "> <chainedmapper> <flattenmapper/> <globmapper from="*" to="-XaddExports:${module.name}/*=junit"/> </chainedmapper> </pathconvert> 2nd) Extend Junit task to automatically set the -XPatch, -XaddExports, -XaddReads, -addmods options for modular execution. This will require adding more attributes to JUnit task (path to test classes to do the -XPatch, ability to disable the automatic options). As the 2nd solution is a superset of the 1st one I will start with it. Any thoughts and comments are welcome Thanks, — Tomas --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@ant.apache.org For additional commands, e-mail: dev-h...@ant.apache.org