- 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 featuremaster
| @@ -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> | |||
| @@ -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; | |||
| } | |||
| @@ -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); | |||
| @@ -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); | |||
| @@ -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); | |||
| } | |||
| } | |||