From 932c7653594cafee05afa62df5b89a6d887d2669 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Fri, 29 Jan 2016 08:54:25 +0100 Subject: [PATCH] Write XML report even when there are no tests Issue: #86 --- .../gen5/console/tasks/XmlReportData.java | 4 ++ .../gen5/console/tasks/XmlReportWriter.java | 39 ++++++---------- .../tasks/XmlReportsWritingListener.java | 10 +++- .../console/tasks/XmlReportAssertions.java | 46 +++++++++++++++++++ .../console/tasks/XmlReportWriterTests.java | 45 ++++++++++++++++++ .../tasks/XmlReportsWritingListenerTests.java | 29 +----------- 6 files changed, 118 insertions(+), 55 deletions(-) create mode 100644 junit-tests/src/test/java/org/junit/gen5/console/tasks/XmlReportAssertions.java create mode 100644 junit-tests/src/test/java/org/junit/gen5/console/tasks/XmlReportWriterTests.java diff --git a/junit-console/src/main/java/org/junit/gen5/console/tasks/XmlReportData.java b/junit-console/src/main/java/org/junit/gen5/console/tasks/XmlReportData.java index d04cd8ec338..443b69e4da4 100644 --- a/junit-console/src/main/java/org/junit/gen5/console/tasks/XmlReportData.java +++ b/junit-console/src/main/java/org/junit/gen5/console/tasks/XmlReportData.java @@ -47,6 +47,10 @@ TestPlan getTestPlan() { return testPlan; } + Clock getClock() { + return clock; + } + void markSkipped(TestIdentifier testIdentifier, String reason) { skippedTests.put(testIdentifier, reason == null ? "" : reason); } diff --git a/junit-console/src/main/java/org/junit/gen5/console/tasks/XmlReportWriter.java b/junit-console/src/main/java/org/junit/gen5/console/tasks/XmlReportWriter.java index 79471e653ba..6109324e809 100644 --- a/junit-console/src/main/java/org/junit/gen5/console/tasks/XmlReportWriter.java +++ b/junit-console/src/main/java/org/junit/gen5/console/tasks/XmlReportWriter.java @@ -10,7 +10,6 @@ package org.junit.gen5.console.tasks; -import static java.nio.charset.StandardCharsets.UTF_8; import static java.time.format.DateTimeFormatter.ISO_LOCAL_DATE_TIME; import static java.util.stream.Collectors.toList; import static org.junit.gen5.commons.util.ExceptionUtils.readStackTrace; @@ -18,16 +17,10 @@ import static org.junit.gen5.console.tasks.XmlReportData.isFailure; import static org.junit.gen5.engine.TestExecutionResult.Status.FAILED; -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.OutputStreamWriter; import java.io.Writer; import java.net.InetAddress; import java.net.UnknownHostException; import java.text.NumberFormat; -import java.time.Clock; import java.time.LocalDateTime; import java.util.List; import java.util.Locale; @@ -45,36 +38,30 @@ class XmlReportWriter { private final XmlReportData reportData; - private final Clock clock; - XmlReportWriter(XmlReportData reportData, Clock clock) { + XmlReportWriter(XmlReportData reportData) { this.reportData = reportData; - this.clock = clock; } - void writeXmlReport(TestIdentifier testIdentifier, File xmlFile) throws IOException, XMLStreamException { + void writeXmlReport(TestIdentifier testIdentifier, Writer out) throws XMLStreamException { // @formatter:off List tests = reportData.getTestPlan().getDescendants(testIdentifier) .stream() .filter(TestIdentifier::isTest) .collect(toList()); // @formatter:on - if (!tests.isEmpty()) { - writeXmlReport(testIdentifier, tests, xmlFile); - } + writeXmlReport(testIdentifier, tests, out); } - private void writeXmlReport(TestIdentifier testIdentifier, List tests, File xmlFile) - throws IOException, XMLStreamException { - try (Writer fileWriter = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(xmlFile), UTF_8))) { - XMLOutputFactory factory = XMLOutputFactory.newInstance(); - XMLStreamWriter xmlWriter = factory.createXMLStreamWriter(fileWriter); - xmlWriter.writeStartDocument(); - writeTestsuite(testIdentifier, tests, xmlWriter); - xmlWriter.writeEndDocument(); - xmlWriter.flush(); - xmlWriter.close(); - } + private void writeXmlReport(TestIdentifier testIdentifier, List tests, Writer out) + throws XMLStreamException { + XMLOutputFactory factory = XMLOutputFactory.newInstance(); + XMLStreamWriter xmlWriter = factory.createXMLStreamWriter(out); + xmlWriter.writeStartDocument(); + writeTestsuite(testIdentifier, tests, xmlWriter); + xmlWriter.writeEndDocument(); + xmlWriter.flush(); + xmlWriter.close(); } private void writeTestsuite(TestIdentifier testIdentifier, List tests, XMLStreamWriter writer) @@ -118,7 +105,7 @@ private void writeHostname(XMLStreamWriter writer) throws XMLStreamException { } private void writeTimestamp(XMLStreamWriter writer) throws XMLStreamException { - LocalDateTime now = LocalDateTime.now(clock).withNano(0); + LocalDateTime now = LocalDateTime.now(reportData.getClock()).withNano(0); writer.writeAttribute("timestamp", ISO_LOCAL_DATE_TIME.format(now)); } diff --git a/junit-console/src/main/java/org/junit/gen5/console/tasks/XmlReportsWritingListener.java b/junit-console/src/main/java/org/junit/gen5/console/tasks/XmlReportsWritingListener.java index 0147274f816..2900b6f4d5d 100644 --- a/junit-console/src/main/java/org/junit/gen5/console/tasks/XmlReportsWritingListener.java +++ b/junit-console/src/main/java/org/junit/gen5/console/tasks/XmlReportsWritingListener.java @@ -10,9 +10,15 @@ package org.junit.gen5.console.tasks; +import static java.nio.charset.StandardCharsets.UTF_8; + +import java.io.BufferedWriter; import java.io.File; +import java.io.FileOutputStream; import java.io.IOException; +import java.io.OutputStreamWriter; import java.io.PrintWriter; +import java.io.Writer; import java.nio.file.Files; import java.time.Clock; @@ -83,8 +89,8 @@ private void writeXmlReportInCaseOfRoot(TestIdentifier testIdentifier) { private void writeXmlReportSafely(TestIdentifier testIdentifier) { File xmlFile = new File(reportsDir, "TEST-" + testIdentifier.getUniqueId() + ".xml"); - try { - new XmlReportWriter(reportData, clock).writeXmlReport(testIdentifier, xmlFile); + try (Writer fileWriter = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(xmlFile), UTF_8))) { + new XmlReportWriter(reportData).writeXmlReport(testIdentifier, fileWriter); } catch (XMLStreamException | IOException e) { printException("Could not write file: " + xmlFile, e); diff --git a/junit-tests/src/test/java/org/junit/gen5/console/tasks/XmlReportAssertions.java b/junit-tests/src/test/java/org/junit/gen5/console/tasks/XmlReportAssertions.java new file mode 100644 index 00000000000..6c95a33a0a8 --- /dev/null +++ b/junit-tests/src/test/java/org/junit/gen5/console/tasks/XmlReportAssertions.java @@ -0,0 +1,46 @@ +/* + * Copyright 2015-2016 the original author or authors. + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution and is available at + * + * http://www.eclipse.org/legal/epl-v10.html + */ + +package org.junit.gen5.console.tasks; + +import java.io.StringReader; +import java.net.URL; + +import javax.xml.XMLConstants; +import javax.xml.transform.stream.StreamSource; +import javax.xml.validation.SchemaFactory; +import javax.xml.validation.Validator; + +import org.opentest4j.AssertionFailedError; +import org.xml.sax.SAXException; + +public class XmlReportAssertions { + + private static Validator schemaValidator; + + static String ensureValidAccordingToJenkinsSchema(String content) throws Exception { + try { + getSchemaValidator().validate(new StreamSource(new StringReader(content))); + return content; + } + catch (SAXException e) { + throw new AssertionFailedError("Invalid XML document: " + content, e); + } + } + + private static Validator getSchemaValidator() throws SAXException { + if (schemaValidator == null) { + URL schemaFile = XmlReportsWritingListener.class.getResource("/jenkins-junit.xsd"); + SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); + schemaValidator = schemaFactory.newSchema(schemaFile).newValidator(); + } + return schemaValidator; + } +} diff --git a/junit-tests/src/test/java/org/junit/gen5/console/tasks/XmlReportWriterTests.java b/junit-tests/src/test/java/org/junit/gen5/console/tasks/XmlReportWriterTests.java new file mode 100644 index 00000000000..d4b7c8e5269 --- /dev/null +++ b/junit-tests/src/test/java/org/junit/gen5/console/tasks/XmlReportWriterTests.java @@ -0,0 +1,45 @@ +/* + * Copyright 2015-2016 the original author or authors. + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution and is available at + * + * http://www.eclipse.org/legal/epl-v10.html + */ + +package org.junit.gen5.console.tasks; + +import static java.util.Collections.singleton; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.gen5.commons.util.CollectionUtils.getOnlyElement; +import static org.junit.gen5.console.tasks.XmlReportAssertions.ensureValidAccordingToJenkinsSchema; + +import java.io.StringWriter; +import java.time.Clock; + +import org.junit.gen5.api.Test; +import org.junit.gen5.engine.support.descriptor.EngineDescriptor; +import org.junit.gen5.launcher.TestPlan; + +class XmlReportWriterTests { + + @Test + void writesFileWithoutTestcaseElementsWithoutAnyTests() throws Exception { + TestPlan testPlan = TestPlan.from(singleton(new EngineDescriptor("emptyEngine", "Empty Engine"))); + XmlReportData reportData = new XmlReportData(testPlan, Clock.systemDefaultZone()); + + StringWriter out = new StringWriter(); + new XmlReportWriter(reportData).writeXmlReport(getOnlyElement(testPlan.getRoots()), out); + + String content = ensureValidAccordingToJenkinsSchema(out.toString()); + //@formatter:off + assertThat(content) + .containsSequence( + "") + .doesNotContain(" "File does not exist: " + xmlFile); String content = new String(Files.readAllBytes(xmlFile), UTF_8); - assertValidAccordingToJenkinsSchema(content); - return content; + return ensureValidAccordingToJenkinsSchema(content); } - private static void assertValidAccordingToJenkinsSchema(String content) throws Exception { - try { - schemaValidator.validate(new StreamSource(new StringReader(content))); - } - catch (SAXException e) { - throw new AssertionFailedError("Invalid XML document: " + content, e); - } - } }