Skip to content

Commit 5ada29e

Browse files
committed
Add 'classpath(...)' test suite feature
Resolves #47
1 parent 1cae623 commit 5ada29e

File tree

5 files changed

+93
-2
lines changed

5 files changed

+93
-2
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
# Java Module Testing Gradle Plugin - Changelog
22

3+
## Version 1.5
4+
* [#47](https://github.com/gradlex-org/java-module-testing/issues/47) Add support for Classpath Test Suites
5+
36
## Version 1.4
47
* [#2](https://github.com/gradlex-org/java-module-testing/issues/2) New approach to split Module Path and Classpath for whitebox testing
58
* [#40](https://github.com/gradlex-org/java-module-testing/issues/40) `useJUnitJupiter("")` without version does not fail for empty test directories

README.md

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,14 +103,26 @@ src
103103
| requires org.example.app; // 'main' module into which the tests are patched
104104
| requires org.junit.jupiter.api;
105105
| }
106-
}
107106
```
108107

109108
A whitebox _test source set_ does **not** have a `module-info.java`.
110109
Instead, the _main_ and _test_ classes will be patched together and the test will run in the _main_ module which now includes the test classes as well.
111110
Additional `requires` for the test are defined as shown above.
112111
If the _sources under test_ are located in a different source set (not `main`), this can be configured via `sourcesUnderTest.set("source-set-name")`.
113112

113+
## Classpath Test Suites
114+
115+
An alternative variant of "whitebox" testing is to run testing on the classpath and ignore **all** module information.
116+
This is what [Gradle does without this plugin](https://docs.gradle.org/current/userguide/java_testing.html#whitebox_unit_test_execution_on_the_classpath).
117+
By default, this plugin replaces this with the [Whitebox Test Suite setup](#whitebox-test-suites), which should be the preferred testing approach.
118+
If you still need to use the classpath-based setup for a Test Suite, you may configure it as follows:
119+
120+
```
121+
javaModuleTesting.classpath(testing.suites["test"])
122+
```
123+
124+
A reason to do testing like this is if you need to utilise testing libraries (e.g. for mocking) that do not work with the Module System at all.
125+
114126
# What does the plugin do?
115127

116128
The plugin rewires the inputs of test compilation (`:compileTestJava`) and test runtime (`:test`).

src/main/java/org/gradlex/javamodule/testing/JavaModuleTestingExtension.java

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package org.gradlex.javamodule.testing;
1818

1919
import org.gradle.api.Action;
20+
import org.gradle.api.Describable;
2021
import org.gradle.api.Project;
2122
import org.gradle.api.artifacts.Configuration;
2223
import org.gradle.api.artifacts.ConfigurationContainer;
@@ -98,6 +99,24 @@ public void whitebox(TestSuite jvmTestSuite) {
9899
whitebox(jvmTestSuite, NO_OP_ACTION);
99100
}
100101

102+
/**
103+
* Turn the given JVM Test Suite into a Classpath Test Suite.
104+
* For example:
105+
* <p>
106+
* javaModuleTesting.classpath(testing.suites["test"])
107+
* <p>
108+
* This restores the default behavior of Gradle to run tests on the Classpath if
109+
* no 'module-info.java' is present in the source folder of the given test suite.
110+
*
111+
* @param jvmTestSuite the JVM Test Suite to configure
112+
*/
113+
@SuppressWarnings("unused")
114+
public void classpath(TestSuite jvmTestSuite) {
115+
if (jvmTestSuite instanceof JvmTestSuite) {
116+
revertJvmTestSuiteForWhitebox((JvmTestSuite) jvmTestSuite);
117+
}
118+
}
119+
101120
/**
102121
* Turn the given JVM Test Suite into a Whitebox Test Suite.
103122
* If needed, configure additional 'requires' and open the
@@ -249,4 +268,25 @@ private void configureJvmTestSuiteForWhitebox(JvmTestSuite jvmTestSuite, Whitebo
249268
}
250269
});
251270
}
271+
272+
/**
273+
* Resets changes performed in 'configureJvmTestSuiteForWhitebox' to Gradle defaults.
274+
*/
275+
private void revertJvmTestSuiteForWhitebox(JvmTestSuite jvmTestSuite) {
276+
TaskContainer tasks = project.getTasks();
277+
SourceSet testSources = jvmTestSuite.getSources();
278+
279+
tasks.named(testSources.getCompileJavaTaskName(), JavaCompile.class, compileJava -> {
280+
compileJava.setClasspath(testSources.getCompileClasspath());
281+
compileJava.getOptions().getCompilerArgumentProviders().removeIf(p -> p instanceof WhiteboxTestCompileArgumentProvider);
282+
compileJava.getActions().removeIf(a -> a instanceof Describable
283+
&& JavaCompileSetModulePathAction.class.getName().equals(((Describable) a).getDisplayName()));
284+
});
285+
286+
tasks.named(testSources.getName(), Test.class, test -> {
287+
test.setClasspath(testSources.getRuntimeClasspath());
288+
test.setTestClassesDirs(testSources.getOutput().getClassesDirs());
289+
test.getJvmArgumentProviders().removeIf(p -> p instanceof WhiteboxTestRuntimeArgumentProvider);
290+
});
291+
}
252292
}

src/main/java/org/gradlex/javamodule/testing/internal/actions/JavaCompileSetModulePathAction.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package org.gradlex.javamodule.testing.internal.actions;
1818

1919
import org.gradle.api.Action;
20+
import org.gradle.api.Describable;
2021
import org.gradle.api.NonNullApi;
2122
import org.gradle.api.Task;
2223
import org.gradle.api.file.FileCollection;
@@ -28,11 +29,16 @@
2829
import java.util.List;
2930

3031
@NonNullApi
31-
public abstract class JavaCompileSetModulePathAction implements Action<Task> {
32+
public abstract class JavaCompileSetModulePathAction implements Action<Task>, Describable {
3233

3334
@Inject
3435
protected abstract JavaModuleDetector getJavaModuleDetector();
3536

37+
@Override
38+
public String getDisplayName() {
39+
return JavaCompileSetModulePathAction.class.getName();
40+
}
41+
3642
@Override
3743
public void execute(Task task) {
3844
JavaCompile javaCompile = (JavaCompile) task;
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package org.gradlex.javamodule.testing.test
2+
3+
import org.gradle.testkit.runner.TaskOutcome
4+
import org.gradlex.javamodule.testing.test.fixture.GradleBuild
5+
import spock.lang.Specification
6+
7+
class ClasspathSuiteTest extends Specification {
8+
9+
@Delegate
10+
GradleBuild build = new GradleBuild()
11+
12+
def "can configure classpath test suite"() {
13+
given:
14+
appBuildFile << '''
15+
javaModuleTesting.classpath(testing.suites["test"])
16+
'''
17+
appModuleInfoFile << '''
18+
module org.example.app {
19+
}
20+
'''
21+
22+
when:
23+
def result = runTests()
24+
25+
then:
26+
result.output.contains('Main Module: null')
27+
result.output.contains('Test Module: null')
28+
result.task(':app:test').outcome == TaskOutcome.SUCCESS
29+
}
30+
}

0 commit comments

Comments
 (0)