- 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"> | <path id="test.classpath"> | ||||
| <pathelement location="${build.classes.dir}"/> | <pathelement location="${build.classes.dir}"/> | ||||
| <path refid="junit.platform.classpath"/> | |||||
| <path refid="junit.engine.vintage.classpath"/> | <path refid="junit.engine.vintage.classpath"/> | ||||
| <path refid="junit.engine.jupiter.classpath"/> | <path refid="junit.engine.jupiter.classpath"/> | ||||
| </path> | </path> | ||||
| @@ -166,5 +165,50 @@ | |||||
| </test> | </test> | ||||
| </junitlauncher> | </junitlauncher> | ||||
| </target> | </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> | </project> | ||||
| @@ -41,7 +41,7 @@ import java.io.File; | |||||
| public class ForkDefinition { | public class ForkDefinition { | ||||
| private boolean includeAntRuntimeLibraries = true; | private boolean includeAntRuntimeLibraries = true; | ||||
| private boolean includeJunitPlatformLibraries = true; | |||||
| private boolean includeJUnitPlatformLibraries = true; | |||||
| private final CommandlineJava commandLineJava; | private final CommandlineJava commandLineJava; | ||||
| private final Environment env = new Environment(); | private final Environment env = new Environment(); | ||||
| @@ -69,6 +69,14 @@ public class ForkDefinition { | |||||
| return this.timeout; | 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() { | public Commandline.Argument createJvmArg() { | ||||
| return this.commandLineJava.createVmArgument(); | return this.commandLineJava.createVmArgument(); | ||||
| } | } | ||||
| @@ -121,19 +129,23 @@ public class ForkDefinition { | |||||
| addAntRuntimeResourceSource(antRuntimeResourceSources, task, toResourceName(AntMain.class)); | addAntRuntimeResourceSource(antRuntimeResourceSources, task, toResourceName(AntMain.class)); | ||||
| addAntRuntimeResourceSource(antRuntimeResourceSources, task, toResourceName(Task.class)); | addAntRuntimeResourceSource(antRuntimeResourceSources, task, toResourceName(Task.class)); | ||||
| addAntRuntimeResourceSource(antRuntimeResourceSources, task, toResourceName(JUnitLauncherTask.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 | // platform-engine | ||||
| addAntRuntimeResourceSource(antRuntimeResourceSources, task, toResourceName(TestEngine.class)); | addAntRuntimeResourceSource(antRuntimeResourceSources, task, toResourceName(TestEngine.class)); | ||||
| // platform-launcher | // platform-launcher | ||||
| addAntRuntimeResourceSource(antRuntimeResourceSources, task, toResourceName(LauncherFactory.class)); | addAntRuntimeResourceSource(antRuntimeResourceSources, task, toResourceName(LauncherFactory.class)); | ||||
| // platform-commons | // platform-commons | ||||
| addAntRuntimeResourceSource(antRuntimeResourceSources, task, toResourceName(Testable.class)); | 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); | final Path classPath = cmdLine.createClasspath(project); | ||||
| classPath.createPath().append(antRuntimeResourceSources); | classPath.createPath().append(antRuntimeResourceSources); | ||||
| return cmdLine; | return cmdLine; | ||||
| } | } | ||||
| @@ -98,7 +98,6 @@ public class StandaloneLauncher { | |||||
| i = i + numArgsConsumed; | i = i + numArgsConsumed; | ||||
| } | } | ||||
| launchDefinition.setTestExecutionContext(forkedExecution); | launchDefinition.setTestExecutionContext(forkedExecution); | ||||
| final LauncherSupport launcherSupport = new LauncherSupport(launchDefinition); | final LauncherSupport launcherSupport = new LauncherSupport(launchDefinition); | ||||
| try { | try { | ||||
| @@ -106,8 +105,8 @@ public class StandaloneLauncher { | |||||
| } catch (Throwable t) { | } catch (Throwable t) { | ||||
| if (launcherSupport.hasTestFailures()) { | if (launcherSupport.hasTestFailures()) { | ||||
| System.exit(Constants.FORK_EXIT_CODE_TESTS_FAILED); | System.exit(Constants.FORK_EXIT_CODE_TESTS_FAILED); | ||||
| throw t; | |||||
| } | } | ||||
| throw t; | |||||
| } | } | ||||
| if (launcherSupport.hasTestFailures()) { | if (launcherSupport.hasTestFailures()) { | ||||
| System.exit(Constants.FORK_EXIT_CODE_TESTS_FAILED); | System.exit(Constants.FORK_EXIT_CODE_TESTS_FAILED); | ||||
| @@ -187,6 +187,77 @@ public class JUnitLauncherTaskTest { | |||||
| ForkedTest.class.getName(), "testSysProp")); | 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) { | private Path setupTrackerProperty(final String targetName) { | ||||
| final String filename = targetName + "-tracker.txt"; | final String filename = targetName + "-tracker.txt"; | ||||
| buildRule.getProject().setProperty(targetName + ".tracker", filename); | 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 { | 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); | return lines.contains(PREFIX_TEST_CLASS_STARTED + className); | ||||
| } | } | ||||
| public static boolean wasTestRun(final Path trackerFile, final String className, final String methodName) throws IOException { | 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); | return lines.contains(PREFIX_TEST_METHOD_STARTED + className + "#" + methodName); | ||||
| } | } | ||||
| public static boolean verifyFailed(final Path trackerFile, final String className, final String methodName) throws IOException { | 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); | 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 { | 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); | 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 { | 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); | 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); | |||||
| } | |||||
| } | } | ||||