Skip to content

Commit

Permalink
Always include leaf nodes to ensure failures are reported
Browse files Browse the repository at this point in the history
Prior to this commit, failing containers were only reported in case they
contained at least one test. However, for example for a parameterized
Jupiter tests and an exception in a `@BeforeAll` method, that led to
failures being silently swallowed. Now, in addition to tests, leaf
nodes of the test tree are always included in the XML report, even if
they are containers, not tests.

Fixes #2537.
  • Loading branch information
marcphilipp committed Jan 31, 2021
1 parent eab6490 commit bb00d66
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
import org.junit.platform.engine.TestExecutionResult;
import org.junit.platform.engine.reporting.ReportEntry;
import org.junit.platform.launcher.TestIdentifier;
import org.junit.platform.launcher.TestPlan;
import org.junit.platform.reporting.legacy.LegacyReportingUtils;

/**
Expand All @@ -62,14 +63,19 @@ class XmlReportWriter {
this.reportData = reportData;
}

void writeXmlReport(TestIdentifier testIdentifier, Writer out) throws XMLStreamException {
void writeXmlReport(TestIdentifier rootDescriptor, Writer out) throws XMLStreamException {
TestPlan testPlan = this.reportData.getTestPlan();
// @formatter:off
List<TestIdentifier> tests = this.reportData.getTestPlan().getDescendants(testIdentifier)
List<TestIdentifier> tests = testPlan.getDescendants(rootDescriptor)
.stream()
.filter(TestIdentifier::isTest)
.filter(testIdentifier -> shouldInclude(testPlan, testIdentifier))
.collect(toList());
// @formatter:on
writeXmlReport(testIdentifier, tests, out);
writeXmlReport(rootDescriptor, tests, out);
}

private boolean shouldInclude(TestPlan testPlan, TestIdentifier testIdentifier) {
return testIdentifier.isTest() || testPlan.getChildren(testIdentifier).isEmpty();
}

private void writeXmlReport(TestIdentifier testIdentifier, List<TestIdentifier> tests, Writer out)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,11 @@
*/
class LegacyXmlReportGeneratingListenerTests {

@TempDir
Path tempDirectory;

@Test
void writesFileForSingleSucceedingTest(@TempDir Path tempDirectory) throws Exception {
void writesFileForSingleSucceedingTest() throws Exception {
var engine = new DemoHierarchicalTestEngine("dummy");
engine.addTest("succeedingTest", "display<-->Name 😎", () -> {
});
Expand Down Expand Up @@ -89,7 +92,7 @@ void writesFileForSingleSucceedingTest(@TempDir Path tempDirectory) throws Excep
}

@Test
void writesFileForSingleFailingTest(@TempDir Path tempDirectory) throws Exception {
void writesFileForSingleFailingTest() throws Exception {
var engine = new DemoHierarchicalTestEngine("dummy");
engine.addTest("failingTest", () -> fail("expected to <b>fail</b>"));

Expand All @@ -115,7 +118,7 @@ void writesFileForSingleFailingTest(@TempDir Path tempDirectory) throws Exceptio
}

@Test
void writesFileForSingleErroneousTest(@TempDir Path tempDirectory) throws Exception {
void writesFileForSingleErroneousTest() throws Exception {
var engine = new DemoHierarchicalTestEngine("dummy");
engine.addTest("failingTest", () -> {
throw new RuntimeException("error occurred");
Expand Down Expand Up @@ -143,7 +146,7 @@ void writesFileForSingleErroneousTest(@TempDir Path tempDirectory) throws Except
}

@Test
void writesFileForSingleSkippedTest(@TempDir Path tempDirectory) throws Exception {
void writesFileForSingleSkippedTest() throws Exception {
var engine = new DemoHierarchicalTestEngine("dummy");
var testDescriptor = engine.addTest("skippedTest", () -> fail("never called"));
testDescriptor.markSkipped("should be skipped");
Expand All @@ -167,7 +170,7 @@ void writesFileForSingleSkippedTest(@TempDir Path tempDirectory) throws Exceptio

@SuppressWarnings("ConstantConditions")
@Test
void writesFileForSingleAbortedTest(@TempDir Path tempDirectory) throws Exception {
void writesFileForSingleAbortedTest() throws Exception {
var engine = new DemoHierarchicalTestEngine("dummy");
engine.addTest("abortedTest", () -> assumeFalse(true, "deliberately aborted"));

Expand All @@ -190,7 +193,7 @@ void writesFileForSingleAbortedTest(@TempDir Path tempDirectory) throws Exceptio
}

@Test
void measuresTimesInSeconds(@TempDir Path tempDirectory) throws Exception {
void measuresTimesInSeconds() throws Exception {
var engine = new DemoHierarchicalTestEngine("dummy");
engine.addTest("firstTest", () -> {
});
Expand All @@ -216,7 +219,7 @@ void measuresTimesInSeconds(@TempDir Path tempDirectory) throws Exception {
}

@Test
void testWithImmeasurableTimeIsOutputCorrectly(@TempDir Path tempDirectory) throws Exception {
void testWithImmeasurableTimeIsOutputCorrectly() throws Exception {
var engine = new DemoHierarchicalTestEngine("dummy");
engine.addTest("test", () -> {
});
Expand All @@ -229,7 +232,7 @@ void testWithImmeasurableTimeIsOutputCorrectly(@TempDir Path tempDirectory) thro
}

@Test
void writesFileForSkippedContainer(@TempDir Path tempDirectory) throws Exception {
void writesFileForSkippedContainer() throws Exception {
var engine = new DemoHierarchicalTestEngine("dummy");
engine.addTest("test", () -> fail("never called"));
engine.getEngineDescriptor().markSkipped("should be skipped");
Expand All @@ -247,7 +250,7 @@ void writesFileForSkippedContainer(@TempDir Path tempDirectory) throws Exception
}

@Test
void writesFileForFailingContainer(@TempDir Path tempDirectory) throws Exception {
void writesFileForFailingContainer() throws Exception {
var engine = new DemoHierarchicalTestEngine("dummy");
engine.addTest("test", () -> fail("never called"));
engine.getEngineDescriptor().setBeforeAllBehavior(() -> fail("failure before all tests"));
Expand All @@ -269,7 +272,31 @@ void writesFileForFailingContainer(@TempDir Path tempDirectory) throws Exception
}

@Test
void writesSystemProperties(@TempDir Path tempDirectory) throws Exception {
void writesFileForFailingContainerWithoutTest() throws Exception {
var engine = new DemoHierarchicalTestEngine("dummy");
engine.addContainer("failingContainer", () -> {
throw new RuntimeException("boom");
});

executeTests(engine, tempDirectory);

var testsuite = readValidXmlFile(tempDirectory.resolve("TEST-dummy.xml"));

assertThat(testsuite.attr("tests", int.class)).isEqualTo(1);
assertThat(testsuite.attr("errors", int.class)).isEqualTo(1);

var testcase = testsuite.child("testcase");
assertThat(testcase.attr("name")).isEqualTo("failingContainer");
assertThat(testcase.attr("classname")).isEqualTo("dummy");

var error = testcase.child("error");
assertThat(error.attr("message")).isEqualTo("boom");
assertThat(error.attr("type")).isEqualTo(RuntimeException.class.getName());
assertThat(error.text()).containsSubsequence("RuntimeException: boom", "\tat");
}

@Test
void writesSystemProperties() throws Exception {
var engine = new DemoHierarchicalTestEngine("dummy");
engine.addTest("test", () -> {
});
Expand All @@ -283,7 +310,7 @@ void writesSystemProperties(@TempDir Path tempDirectory) throws Exception {
}

@Test
void writesHostNameAndTimestamp(@TempDir Path tempDirectory) throws Exception {
void writesHostNameAndTimestamp() throws Exception {
var engine = new DemoHierarchicalTestEngine("dummy");
engine.addTest("test", () -> {
});
Expand All @@ -299,7 +326,7 @@ void writesHostNameAndTimestamp(@TempDir Path tempDirectory) throws Exception {
}

@Test
void printsExceptionWhenReportsDirCannotBeCreated(@TempDir Path tempDirectory) throws Exception {
void printsExceptionWhenReportsDirCannotBeCreated() throws Exception {
var reportsDir = tempDirectory.resolve("dummy.txt");
Files.write(reportsDir, Set.of("content"));

Expand All @@ -313,7 +340,7 @@ void printsExceptionWhenReportsDirCannotBeCreated(@TempDir Path tempDirectory) t
}

@Test
void printsExceptionWhenReportCouldNotBeWritten(@TempDir Path tempDirectory) throws Exception {
void printsExceptionWhenReportCouldNotBeWritten() throws Exception {
var engineDescriptor = new EngineDescriptor(UniqueId.forEngine("engine"), "Engine");

var xmlFile = tempDirectory.resolve("TEST-engine.xml");
Expand All @@ -329,7 +356,7 @@ void printsExceptionWhenReportCouldNotBeWritten(@TempDir Path tempDirectory) thr
}

@Test
void writesReportEntriesToSystemOutElement(@TempDir Path tempDirectory) throws Exception {
void writesReportEntriesToSystemOutElement() throws Exception {
var engineDescriptor = new EngineDescriptor(UniqueId.forEngine("engine"), "Engine");
engineDescriptor.addChild(new TestDescriptorStub(UniqueId.root("child", "test"), "test"));
var testPlan = TestPlan.from(Set.of(engineDescriptor));
Expand Down

0 comments on commit bb00d66

Please sign in to comment.