This is an automated email from the ASF dual-hosted git repository.
jaikiran pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ant.git
The following commit(s) were added to refs/heads/master by this push:
new 2d4414817 fix legacy-xml reporting in junitlauncher task, when jupiter
dynamic tests are involved.
2d4414817 is described below
commit 2d4414817a8e366b2c38cae5ace9fe5206677790
Author: Jaikiran Pai <[email protected]>
AuthorDate: Sun Aug 13 21:42:57 2023 +0530
fix legacy-xml reporting in junitlauncher task, when jupiter dynamic tests
are involved.
Thanks to Marc Guillemot for raising the issue and proposing a patch
This closes #122 pull request on github
---
WHATSNEW | 5 ++
.../testcases/taskdefs/optional/junitlauncher.xml | 18 +++++++
.../junitlauncher/LegacyXmlResultFormatter.java | 23 ++++++--
.../junitlauncher/JUnitLauncherTaskTest.java | 61 +++++++++++++++++----
.../junitlauncher/jupiter/JupiterDynamicTests.java | 63 ++++++++++++++++++++++
5 files changed, 156 insertions(+), 14 deletions(-)
diff --git a/WHATSNEW b/WHATSNEW
index c07344b42..52be5c754 100644
--- a/WHATSNEW
+++ b/WHATSNEW
@@ -50,6 +50,11 @@ Fixed bugs:
a CEN extra field data for the entry.
Bugzilla Report 66873
+ * legacy-xml listener of junitlauncher task wouldn't report certain
+ failures involving junit jupiter dynamic tests. This has now been
+ fixed.
+ Github Pull Request #122
+
Other changes:
--------------
diff --git a/src/etc/testcases/taskdefs/optional/junitlauncher.xml
b/src/etc/testcases/taskdefs/optional/junitlauncher.xml
index 0a736d714..c3e4b5651 100644
--- a/src/etc/testcases/taskdefs/optional/junitlauncher.xml
+++ b/src/etc/testcases/taskdefs/optional/junitlauncher.xml
@@ -484,5 +484,23 @@
</test>
</junitlauncher>
</target>
+
+ <target name="test-jupiter-dynamic-tests" depends="init">
+ <property name="junitlauncher.test.tracker.append.file"
+ value="${output.dir}/${test-jupiter-dynamic-tests.tracker}"/>
+ <junitlauncher>
+ <classpath refid="test.classpath"/>
+ <test name="org.example.junitlauncher.jupiter.JupiterDynamicTests"
+ outputdir="${output.dir}">
+ <fork>
+ <sysproperty key="junitlauncher.test.failBeforeEach"
value="true"/>
+ </fork>
+ <listener classname="org.example.junitlauncher.Tracker"
+ if="test-jupiter-dynamic-tests.tracker"/>
+ <listener type="legacy-xml" sendSysErr="true" sendSysOut="true"
+ resultFile="JupiterDynamicTests.xml"/>
+ </test>
+ </junitlauncher>
+ </target>
</project>
diff --git
a/src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/LegacyXmlResultFormatter.java
b/src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/LegacyXmlResultFormatter.java
index 3db122791..f72822d38 100644
---
a/src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/LegacyXmlResultFormatter.java
+++
b/src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/LegacyXmlResultFormatter.java
@@ -24,6 +24,7 @@ import org.junit.platform.engine.TestExecutionResult;
import org.junit.platform.engine.TestSource;
import org.junit.platform.engine.reporting.ReportEntry;
import org.junit.platform.engine.support.descriptor.ClassSource;
+import org.junit.platform.engine.support.descriptor.MethodSource;
import org.junit.platform.launcher.TestIdentifier;
import org.junit.platform.launcher.TestPlan;
@@ -244,6 +245,7 @@ class LegacyXmlResultFormatter extends
AbstractJUnitResultFormatter implements T
// (https://bz.apache.org/bugzilla/show_bug.cgi?id=63850)
continue;
}
+ String classname = null;
// find the associated class of this test
final Optional<ClassSource> parentClassSource;
if (testId.isTest()) {
@@ -252,10 +254,25 @@ class LegacyXmlResultFormatter extends
AbstractJUnitResultFormatter implements T
else {
parentClassSource = findFirstClassSource(testId);
}
- if (!parentClassSource.isPresent()) {
- continue;
+ if (parentClassSource.isPresent()) {
+ classname = parentClassSource.get().getClassName();
+ } else {
+ if (testId.getSource().isPresent()) {
+ final TestSource testSource = testId.getSource().get();
+ if (testSource instanceof MethodSource) {
+ // this can happen for the case where the test is
generated dynamically
+ // through the use of
@org.junit.jupiter.api.TestFactory. In such cases
+ // the method having that annotation is considered
a test and its
+ // source is reported as a MethodSource
+ classname = ((MethodSource)
testSource).getClassName();
+ }
+ }
+ }
+ if (classname == null) {
+ // as a last resort, use the test id as the classname,
+ // so that the failure does get reported instead of being
ignored/invisible
+ classname = testId.getUniqueIdObject().toString();
}
- final String classname =
(parentClassSource.get()).getClassName();
writer.writeStartElement(ELEM_TESTCASE);
writeAttribute(writer, ATTR_CLASSNAME, classname);
writeAttribute(writer, ATTR_NAME, useLegacyReportingName ?
testId.getLegacyReportingName()
diff --git
a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/junitlauncher/JUnitLauncherTaskTest.java
b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/junitlauncher/JUnitLauncherTaskTest.java
index 051c23eef..8d6455311 100644
---
a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/junitlauncher/JUnitLauncherTaskTest.java
+++
b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/junitlauncher/JUnitLauncherTaskTest.java
@@ -40,6 +40,7 @@ import org.apache.tools.ant.Project;
import org.apache.tools.ant.taskdefs.condition.Os;
import
org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.JUnitLauncherTask;
import org.apache.tools.ant.util.LoaderUtils;
+import org.example.junitlauncher.jupiter.JupiterDynamicTests;
import org.example.junitlauncher.jupiter.JupiterSampleTest;
import org.example.junitlauncher.jupiter.JupiterSampleTestFailingBeforeAll;
import org.example.junitlauncher.jupiter.JupiterTagSampleTest;
@@ -184,17 +185,8 @@ public class JUnitLauncherTaskTest {
JupiterSampleTest.class.getName(), "testSkipped"));
assertFalse("ForkedTest wasn't expected to be run",
wasTestRun(trackerFile, ForkedTest.class.getName()));
-
verifyLegacyXMLFile("TEST-org.example.junitlauncher.jupiter.JupiterSampleTestFailingBeforeAll.xml",
"<failure message=\"Intentional failure\"
type=\"java.lang.RuntimeException\">");
-
verifyLegacyXMLFile("TEST-org.example.junitlauncher.jupiter.JupiterSampleTestFailingStatic.xml",
"Caused by: java.lang.RuntimeException: Intentional exception from static init
block");
- }
-
- private void verifyLegacyXMLFile(final String fileName, final String
expectedContentExtract) throws IOException {
- final String outputDir =
buildRule.getProject().getProperty("output.dir");
- final Path xmlFile = Paths.get(outputDir, fileName);
-
- assertTrue("XML file doesn't exist: " + xmlFile,
Files.exists(xmlFile));
- final String content = new String(Files.readAllBytes(xmlFile),
StandardCharsets.UTF_8);
- assertTrue(fileName + " doesn't contain " + expectedContentExtract,
content.contains(expectedContentExtract));
+
assertPresentInLegacyXMLFile("TEST-org.example.junitlauncher.jupiter.JupiterSampleTestFailingBeforeAll.xml",
"<failure message=\"Intentional failure\"
type=\"java.lang.RuntimeException\">");
+
assertPresentInLegacyXMLFile("TEST-org.example.junitlauncher.jupiter.JupiterSampleTestFailingStatic.xml",
"Caused by: java.lang.RuntimeException: Intentional exception from static init
block");
}
/**
@@ -562,6 +554,53 @@ public class JUnitLauncherTaskTest {
wasTestRun(trackerFile,
SharedDataAccessorTest1.class.getName()));
}
+ /**
+ * Tests that dynamically generated jupiter tests, when they fail, are
reported
+ * correctly by the legacy-xml reporter
+ */
+ @Test
+ public void testJupiterDynamicTests() throws Exception {
+ final String targetName = "test-jupiter-dynamic-tests";
+ final Path trackerFile = setupTrackerProperty(targetName);
+ buildRule.executeTarget(targetName);
+
+ assertTrue("JupiterDynamicTests was expected to be run",
+ wasTestRun(trackerFile, JupiterDynamicTests.class.getName()));
+ final String xmlReportFile = "JupiterDynamicTests.xml";
+ final String testClassName = JupiterDynamicTests.class.getName();
+ assertPresentInLegacyXMLFile(xmlReportFile, "@BeforeEach called on " +
testClassName);
+ assertAbsentInLegacyXMLFile(xmlReportFile, "@TestFactory called");
+ assertPresentInLegacyXMLFile(xmlReportFile,
+ "<failure message=\"Intentionally failing in @BeforeEach of "
+ testClassName);
+ }
+
+ private void assertPresentInLegacyXMLFile(final String fileName,
+ final String expectedContent)
throws IOException {
+ assertInLegacyXMLFile(fileName, expectedContent, true);
+ }
+
+ private void assertAbsentInLegacyXMLFile(final String fileName,
+ final String unexpectedContent)
throws IOException {
+ assertInLegacyXMLFile(fileName, unexpectedContent, false);
+ }
+
+ private void assertInLegacyXMLFile(final String fileName, final String
content,
+ final boolean expected) throws
IOException {
+ final String outputDir =
buildRule.getProject().getProperty("output.dir");
+ final Path xmlFile = Paths.get(outputDir, fileName);
+
+ assertTrue("XML file doesn't exist: " + xmlFile,
Files.exists(xmlFile));
+ final String actualContent = new String(Files.readAllBytes(xmlFile),
StandardCharsets.UTF_8);
+ if (expected) {
+ assertTrue(fileName + " doesn't contain " + content,
+ actualContent.contains(content));
+ } else {
+ assertFalse(fileName + " unexpectedly contains " + content,
+ actualContent.contains(content));
+ }
+
+ }
+
private Path setupTrackerProperty(final String targetName) {
final String filename = targetName + "-tracker.txt";
buildRule.getProject().setProperty(targetName + ".tracker", filename);
diff --git
a/src/tests/junit/org/example/junitlauncher/jupiter/JupiterDynamicTests.java
b/src/tests/junit/org/example/junitlauncher/jupiter/JupiterDynamicTests.java
new file mode 100644
index 000000000..0413b795c
--- /dev/null
+++ b/src/tests/junit/org/example/junitlauncher/jupiter/JupiterDynamicTests.java
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.example.junitlauncher.jupiter;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DynamicContainer;
+import org.junit.jupiter.api.DynamicTest;
+import org.junit.jupiter.api.TestFactory;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class JupiterDynamicTests {
+
+ @TestFactory
+ Collection<DynamicContainer> generateTests() {
+ System.out.println("@TestFactory called on " + this);
+ final DynamicTest test1 = DynamicTest.dynamicTest(
+ "Dynamic test1",
+ () -> {
+ System.out.println("Dynamic test1 being executed on " +
this);
+ assertEquals("foo", "foo");
+ });
+ final DynamicTest test2 = DynamicTest.dynamicTest(
+ "Dynamic test2",
+ () -> {
+ System.out.println("Dynamic test2 being executed on " +
this);
+ assertEquals("bar", "bar");
+ });
+ final List<DynamicTest> tests = new ArrayList<>();
+ tests.add(test1);
+ tests.add(test2);
+ return Collections.singleton(DynamicContainer.dynamicContainer(
+ "Dynamic test container", tests));
+ }
+
+ @BeforeEach
+ void beforeEach() {
+ System.out.println("@BeforeEach called on " + this);
+ final boolean shouldFail =
Boolean.getBoolean("junitlauncher.test.failBeforeEach");
+ if (shouldFail) {
+ throw new RuntimeException("Intentionally failing in @BeforeEach
of " + this);
+ }
+ }
+}