Browse Source

[junitlauncher] More fine-grained control over classpath for forked tests in junitlauncher

- Allows Ant runtime libraries to be excluded and thus letting the user have control over where those library jars come from
- Allows JUnit platform libraries to be excluded and thus letting the user have control over where those library jars come from

Plus added testcases to verify this feature
master
Jaikiran Pai 6 years ago
parent
commit
8590e1539a
5 changed files with 144 additions and 11 deletions
  1. +45
    -1
      src/etc/testcases/taskdefs/optional/junitlauncher.xml
  2. +15
    -3
      src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/ForkDefinition.java
  3. +1
    -2
      src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/StandaloneLauncher.java
  4. +71
    -0
      src/tests/junit/org/apache/tools/ant/taskdefs/optional/junitlauncher/JUnitLauncherTaskTest.java
  5. +12
    -5
      src/tests/junit/org/example/junitlauncher/Tracker.java

+ 45
- 1
src/etc/testcases/taskdefs/optional/junitlauncher.xml View File

@@ -43,7 +43,6 @@

<path id="test.classpath">
<pathelement location="${build.classes.dir}"/>
<path refid="junit.platform.classpath"/>
<path refid="junit.engine.vintage.classpath"/>
<path refid="junit.engine.jupiter.classpath"/>
</path>
@@ -166,5 +165,50 @@
</test>
</junitlauncher>
</target>

<target name="test-junit-platform-lib-excluded" depends="init">
<junitlauncher>
<classpath refid="junit.engine.jupiter.classpath"/>
<classpath>
<pathelement location="${build.classes.dir}"/>
</classpath>
<test name="org.example.junitlauncher.jupiter.JupiterSampleTest" outputdir="${output.dir}">
<!-- expect the test to not be launched due to CNFE on JUnit platform classes -->
<fork dir="${basedir}" includeJUnitPlatformLibraries="false"/>
</test>
</junitlauncher>
</target>

<target name="test-junit-ant-runtime-lib-excluded" depends="init">
<junitlauncher>
<classpath refid="junit.engine.jupiter.classpath"/>
<classpath>
<pathelement location="${build.classes.dir}"/>
</classpath>
<test name="org.example.junitlauncher.jupiter.JupiterSampleTest" outputdir="${output.dir}">
<!-- expect the test to not be launched due to CNFE on Ant runtime classes -->
<fork dir="${basedir}" includeAntRuntimeLibraries="false"/>
</test>
</junitlauncher>
</target>

<target name="test-junit-platform-lib-custom-location" depends="init">
<junitlauncher>
<classpath refid="junit.engine.jupiter.classpath"/>
<classpath>
<pathelement location="${build.classes.dir}"/>
</classpath>
<!-- we set includeJUnitPlatformLibraries=false on the fork element
and then explicitly specify a location of the JUnit platform libraries -->
<classpath refid="junit.platform.classpath"/>
<test name="org.example.junitlauncher.jupiter.JupiterSampleTest" outputdir="${output.dir}">
<listener classname="org.example.junitlauncher.Tracker"
outputDir="${output.dir}"
resultFile="${test-junit-platform-lib-custom-location.tracker}"
if="test-junit-platform-lib-custom-location.tracker"/>
<fork dir="${basedir}" includeJUnitPlatformLibraries="false"/>
</test>
</junitlauncher>
</target>
</project>


+ 15
- 3
src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/ForkDefinition.java View File

@@ -41,7 +41,7 @@ import java.io.File;
public class ForkDefinition {

private boolean includeAntRuntimeLibraries = true;
private boolean includeJunitPlatformLibraries = true;
private boolean includeJUnitPlatformLibraries = true;

private final CommandlineJava commandLineJava;
private final Environment env = new Environment();
@@ -69,6 +69,14 @@ public class ForkDefinition {
return this.timeout;
}

public void setIncludeJUnitPlatformLibraries(final boolean include) {
this.includeJUnitPlatformLibraries = include;
}

public void setIncludeAntRuntimeLibraries(final boolean include) {
this.includeAntRuntimeLibraries = include;
}

public Commandline.Argument createJvmArg() {
return this.commandLineJava.createVmArgument();
}
@@ -121,19 +129,23 @@ public class ForkDefinition {
addAntRuntimeResourceSource(antRuntimeResourceSources, task, toResourceName(AntMain.class));
addAntRuntimeResourceSource(antRuntimeResourceSources, task, toResourceName(Task.class));
addAntRuntimeResourceSource(antRuntimeResourceSources, task, toResourceName(JUnitLauncherTask.class));
} else {
task.log("Excluding Ant runtime libraries from forked JVM classpath", Project.MSG_DEBUG);
}

if (this.includeJunitPlatformLibraries) {
if (this.includeJUnitPlatformLibraries) {
// platform-engine
addAntRuntimeResourceSource(antRuntimeResourceSources, task, toResourceName(TestEngine.class));
// platform-launcher
addAntRuntimeResourceSource(antRuntimeResourceSources, task, toResourceName(LauncherFactory.class));
// platform-commons
addAntRuntimeResourceSource(antRuntimeResourceSources, task, toResourceName(Testable.class));
} else {
task.log("Excluding JUnit platform libraries from forked JVM classpath", Project.MSG_DEBUG);
}
final Path classPath = cmdLine.createClasspath(project);
classPath.createPath().append(antRuntimeResourceSources);


return cmdLine;
}



+ 1
- 2
src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/StandaloneLauncher.java View File

@@ -98,7 +98,6 @@ public class StandaloneLauncher {
i = i + numArgsConsumed;
}


launchDefinition.setTestExecutionContext(forkedExecution);
final LauncherSupport launcherSupport = new LauncherSupport(launchDefinition);
try {
@@ -106,8 +105,8 @@ public class StandaloneLauncher {
} catch (Throwable t) {
if (launcherSupport.hasTestFailures()) {
System.exit(Constants.FORK_EXIT_CODE_TESTS_FAILED);
throw t;
}
throw t;
}
if (launcherSupport.hasTestFailures()) {
System.exit(Constants.FORK_EXIT_CODE_TESTS_FAILED);


+ 71
- 0
src/tests/junit/org/apache/tools/ant/taskdefs/optional/junitlauncher/JUnitLauncherTaskTest.java View File

@@ -187,6 +187,77 @@ public class JUnitLauncherTaskTest {
ForkedTest.class.getName(), "testSysProp"));
}

/**
* Tests that in a forked mode execution of tests, when the {@code includeJUnitPlatformLibraries} attribute
* is set to false, then the execution of such tests fails with a classloading error for the JUnit platform
* classes
*
* @throws Exception
*/
@Test
public void testExcludeJUnitPlatformLibs() throws Exception {
final String targetName = "test-junit-platform-lib-excluded";
try {
buildRule.executeTarget(targetName);
Assert.fail(targetName + " was expected to fail since JUnit platform libraries " +
"weren't included in the classpath of the forked JVM");
} catch (BuildException be) {
// expect a ClassNotFoundException for a JUnit platform class
final String cnfeMessage = ClassNotFoundException.class.getName() + ": org.junit.platform";
if (!buildRule.getFullLog().contains(cnfeMessage)) {
throw be;
}
}
final String exlusionLogMsg = "Excluding JUnit platform libraries";
Assert.assertTrue("JUnit platform libraries weren't excluded from classpath", buildRule.getFullLog().contains(exlusionLogMsg));
}

/**
* Tests that in a forked mode execution of tests, when the {@code includeAntRuntimeLibraries} attribute
* is set to false, then the execution of such tests fails with a classloading error for the Ant runtime
* classes
*
* @throws Exception
*/
@Test
public void testExcludeAntRuntimeLibs() throws Exception {
final String targetName = "test-junit-ant-runtime-lib-excluded";
try {
buildRule.executeTarget(targetName);
Assert.fail(targetName + " was expected to fail since JUnit platform libraries " +
"weren't included in the classpath of the forked JVM");
} catch (BuildException be) {
// expect a Error due to missing main class (which is part of Ant runtime libraries
// that we excluded)
final String missingMainClass = "Could not find or load main class " + StandaloneLauncher.class.getName();
if (!buildRule.getFullLog().contains(missingMainClass)) {
throw be;
}
}
final String exlusionLogMsg = "Excluding Ant runtime libraries";
Assert.assertTrue("Ant runtime libraries weren't excluded from classpath", buildRule.getFullLog().contains(exlusionLogMsg));
}


/**
* Tests that in a forked mode execution, with {@code includeJUnitPlatformLibraries} attribute set to false
* and with the test classpath explicitly including JUnit platform library jars, the tests are executed successfully
*
* @throws Exception
*/
@Test
public void testJUnitPlatformLibsCustomLocation() throws Exception {
final String targetName = "test-junit-platform-lib-custom-location";
final Path trackerFile = setupTrackerProperty(targetName);
buildRule.executeTarget(targetName);
final String exlusionLogMsg = "Excluding JUnit platform libraries";
Assert.assertTrue("JUnit platform libraries weren't excluded from classpath", buildRule.getFullLog().contains(exlusionLogMsg));
Assert.assertTrue("JupiterSampleTest#testSucceeds was expected to succeed", verifySuccess(trackerFile,
JupiterSampleTest.class.getName(), "testSucceeds"));
Assert.assertTrue("JupiterSampleTest#testFails was expected to succeed", verifyFailed(trackerFile,
JupiterSampleTest.class.getName(), "testFails"));
}

private Path setupTrackerProperty(final String targetName) {
final String filename = targetName + "-tracker.txt";
buildRule.getProject().setProperty(targetName + ".tracker", filename);


+ 12
- 5
src/tests/junit/org/example/junitlauncher/Tracker.java View File

@@ -110,27 +110,34 @@ public class Tracker implements TestResultFormatter {
}

public static boolean wasTestRun(final Path trackerFile, final String className) throws IOException {
final List<String> lines = Files.readAllLines(trackerFile);
final List<String> lines = readTrackerFile(trackerFile);
return lines.contains(PREFIX_TEST_CLASS_STARTED + className);
}

public static boolean wasTestRun(final Path trackerFile, final String className, final String methodName) throws IOException {
final List<String> lines = Files.readAllLines(trackerFile);
final List<String> lines = readTrackerFile(trackerFile);
return lines.contains(PREFIX_TEST_METHOD_STARTED + className + "#" + methodName);
}

public static boolean verifyFailed(final Path trackerFile, final String className, final String methodName) throws IOException {
final List<String> lines = Files.readAllLines(trackerFile);
final List<String> lines = readTrackerFile(trackerFile);
return lines.contains(TestExecutionResult.Status.FAILED + ":test-method:" + className + "#" + methodName);
}

public static boolean verifySuccess(final Path trackerFile, final String className, final String methodName) throws IOException {
final List<String> lines = Files.readAllLines(trackerFile);
final List<String> lines = readTrackerFile(trackerFile);
return lines.contains(TestExecutionResult.Status.SUCCESSFUL + ":test-method:" + className + "#" + methodName);
}

public static boolean verifySkipped(final Path trackerFile, final String className, final String methodName) throws IOException {
final List<String> lines = Files.readAllLines(trackerFile);
final List<String> lines = readTrackerFile(trackerFile);
return lines.contains(PREFIX_TEST_METHOD_SKIPPED + className + "#" + methodName);
}

private static List<String> readTrackerFile(final Path trackerFile) throws IOException {
if (!Files.isRegularFile(trackerFile)) {
throw new RuntimeException(trackerFile + " is either missing or not a file");
}
return Files.readAllLines(trackerFile);
}
}

Loading…
Cancel
Save