On Fri, Feb 14, 2020 at 10:31 PM Alex Buckley <alex.buck...@oracle.com> wrote:
> On 2/14/2020 11:29 AM, Christian Stein wrote: > >> A different way to address those use cases would be to ship the > >> logic just described for `--patch-module-descriptor` in a launcher > >> offered by the test framework itself. > > > > That's too late in the build game. You already need this merged > > descriptor at compile time. And you need the user to define the > > additional elements (modifiers and directives), as no build tool > > may infer them always correctly by inspecting the test sources... > > Fair point, and thanks for reminding me about your "Testing In The > Modular World" document. > > The thing I'm having trouble with is that javac already lets you specify > the --add-reads options on org.junit.jupiter.api & friends that are > needed to compile test code. If Maven expects the user to painfully > configure the POM to pass --patch-module-descriptor to javac, why can't > the POM offer an easy way to make Maven itself (in the `test-compile` > phase?) pass some defined-behind-the-scenes --add-reads options? > > Maven and other build tools would add the `--patch-module-descriptor` automacially and point to the user-defined "patch module compilation unit" that only contains the extra directives: like `requires java.sql;`, or `requires org.testng.core;` or ... `requires org.junit.jupiter;`. Or all of them. Those extra directives needed by test modules to compile and run are a deliberate decision made by the user -- on a per test module basis. No build tool may infer those decisions correctly. Similarly, at run time, you propose to always open the main module to > the same org.junit.platform.commons module -- `module-info.test` is more > Not the main module. Only the current test module. Assuming, that you run tests from a single test module at a time. > or less the same for every JUnit project -- so why doesn't the POM have > an easy way to let Maven itself (in the `test` phase?) pass --add-opens > to java? > Opening a module for deep-reflection is just a single aspect of the "Testing In The Modular World" story. Btw. `open module` or `--add-opens` is only required iff the test framework of choice reflects into your test modules. I already have a ServiceProvider-based variation running locally, that uses this standard technique to pass the execution control to the main-like entry-point of each test module. > There are no new modularity "primitives" here (by which I mean features > of the module system itself, such as open modules) ... there is just > detailed configuration which, in the testing context, should be done by > the build tool rather than the user. > Except for configuration parts that cannot be inferred. Here the user has to resort to javac and java command line options, like `--add-reads`, and must negotiate with the build tool how to pass those options. And all of this tedious and errorprone textual configuration **after** having declared a concise, tool-agnostic, well-definend and beautiful inter-module test module using the official `module-info.java` syntax: - test.base/test/module-info.java: open /*test*/ module test.base { requires com.greetings; // module under test requires org.astro; // module under test requires java.sql; // system-provided module needed by test code requires org.junit.jupiter; // framework reflecting entry-points requires org.assertj.core; // ...and more test-related modules } Leaving this compile-able DSL behind **only** for in(tra)-module (white-box) testing is ... inconvenient and hard to explain. Like Robert wrote in his initial request to simplify the usage of patch module. Assuming `--patch-module-descriptor` was already available, the org.astro test story would read: - org.astro/main/module-info.java: module org.astro { exports org.astro; requires java.logging; } - org.astro/test/module-info.java: open /*test*/ module org.astro /*extends main module org.astro*/ { requires java.sql; // system-provided module needed by test code requires org.junit.jupiter; // framework reflecting entry-points requires org.assertj.core; // ...and more test-related modules } A build tool now easily may detect that `--patch-module-descriptor` is required at test compile and run time. It could infer it from the same module name or simply by seeing a main and a test `module-info.java` compilation unit within the sources of the org.astro Maven-/Gradle-/pro-/Bach-/any-build-tool-"module". Build tools could pass the following argument to javac/java while being in their test-scope tasks. Of course, implying that org.astro/test/module-info.java is the current "primary" module descriptor: --patch-module-descriptor org.astro=org.astro/main/module-info.java That's it. The primary test-relevant modular directives are enriched by those of the main module as declared in org.astro/main/module-info.java resulting effectively in a synthetic in-module test module descriptor that resembles the inter-module test descriptor presented above: - SYNTHETIC test module for org.astro open /*test*/ module org.astro /*extends main module org.astro*/ { requires java.sql; // system-provided module needed by test code requires org.junit.jupiter; // framework reflecting entry-points requires org.assertj.core; // ...and more test-related modules // exports org.astro; // patched from org.astro/main/module-info.java requires java.logging; // patched from org.astro/main/module-info.java } Cheers, Christian