Skip to content

Testing with Jigsaw

Sam Brannen edited this page Apr 15, 2017 · 1 revision

Testing with Jigsaw

This page is a collection of thoughts and opinions regarding testing (with JUnit Jupiter and the JUnit Platform) in a modular world with Project Jigsaw.

Example project layout

application/

  src/
    main/
      application.api/
        foo/
          bar/
            api/
              ApplicationVersion.java
              ApplicationInterface.java
        module-info.java = module application.api {
          requires ...; 
          exports foo.bar.application.api;
        }
      application.core/
      application.gui/
      application.main/

    test/
      application.api/
        foo/
          bar/
            api/
              ApplicationVersionTests.java
              ApplicationInterfaceTests.java
        module-info.java = module application.api {
          requires ...;
          exports foo.bar.application.api;
          requires junit.api;
        }
      application.core/
      application.gui/
      application.main/
      integration.api/
          tests/
            ApplicationApiTests.java
        module-info.java = module integration.api { 
          requires application.api;
          requires junit.api;
        }
      integration.main/
          tests/
            ApplicationMainTests.java
        module-info.java = module integration.main {
          requires application.main;
          requires junit.api;
        }

Using pro main compiles to application/target:

target/
  main/
    exploded/
      application.api/
        foo/
          bar/
            api/
              ApplicationVersion.class
              ApplicationInterface.class
        module-info.class
      application.core/
      application.gui/
      application.main/    

In an intermediate step, the test sources are merged with the main source into application/target/test/merged:

target/test/merged/
      application.api/
        foo/
          bar/
            api/
              ApplicationVersion.java
              ApplicationVersionTests.java
              ApplicationInterface.java
              ApplicationInterfaceTests.java
        module-info.java = module application.api { 
          requires ...;
          requires junit.api; 
          exports foo.bar.application.api;
        }

The merged sources are then compiled to application/target/test/exploded:

target/test/exploded/
      application.api/
        foo/
          bar/
            api/
              ApplicationVersion.class
              ApplicationVersionTests.class
              ApplicationInterface.class
              ApplicationInterfaceTests.class
        module-info.class
 ...
      integration.api/
          tests/
            ApplicationApiTests.class
        module-info.class
      integration.main/
          tests/
            ApplicationMainTests.class
        module-info.class

Now, there are "testable" modules in application/target/test/exploded:

application/target/test/exploded/
      application.api/
      application.core/
      application.gui/
      application.main/

      integration.api/
      integration.main/

Here, a shell can iterate over the module folders and invoke the JUnit platform, which discovers *Tests, executes them and generate reports:

java 
    -classpath junit-platform-console-standalone-1.0.0-M4.jar
    -classpath target/test/exploded/[name of module]
  org.junit.platform.console.ConsoleLauncher 
    --scan-classpath