Skip to content

Commit

Permalink
Write XML report even when there are no tests
Browse files Browse the repository at this point in the history
Issue: #86
  • Loading branch information
marcphilipp committed Jan 29, 2016
1 parent 59a95bb commit 932c765
Show file tree
Hide file tree
Showing 6 changed files with 118 additions and 55 deletions.
Expand Up @@ -47,6 +47,10 @@ TestPlan getTestPlan() {
return testPlan;
}

Clock getClock() {
return clock;
}

void markSkipped(TestIdentifier testIdentifier, String reason) {
skippedTests.put(testIdentifier, reason == null ? "" : reason);
}
Expand Down
Expand Up @@ -10,24 +10,17 @@

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;
import static org.junit.gen5.commons.util.StringUtils.isNotBlank;
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;
Expand All @@ -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<TestIdentifier> 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<TestIdentifier> 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<TestIdentifier> 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<TestIdentifier> tests, XMLStreamWriter writer)
Expand Down Expand Up @@ -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));
}

Expand Down
Expand Up @@ -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;

Expand Down Expand Up @@ -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);
Expand Down
@@ -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;
}
}
@@ -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(
"<testsuite name=\"Empty Engine\" tests=\"0\"",
"</testsuite>")
.doesNotContain("<testcase");
//@formatter:on
}

}
Expand Up @@ -15,17 +15,16 @@
import static org.junit.gen5.api.Assertions.assertTrue;
import static org.junit.gen5.api.Assertions.fail;
import static org.junit.gen5.api.Assumptions.assumeFalse;
import static org.junit.gen5.console.tasks.XmlReportAssertions.ensureValidAccordingToJenkinsSchema;
import static org.junit.gen5.engine.discovery.UniqueIdSelector.forUniqueId;
import static org.junit.gen5.launcher.main.LauncherFactoryForTestingPurposesOnly.createLauncher;
import static org.junit.gen5.launcher.main.TestDiscoveryRequestBuilder.request;

import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringReader;
import java.io.StringWriter;
import java.net.InetAddress;
import java.net.URL;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
Expand All @@ -38,13 +37,7 @@
import java.time.ZoneId;
import java.time.ZonedDateTime;

import javax.xml.XMLConstants;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Validator;

import org.junit.gen5.api.AfterEach;
import org.junit.gen5.api.BeforeAll;
import org.junit.gen5.api.BeforeEach;
import org.junit.gen5.api.Test;
import org.junit.gen5.api.TestInfo;
Expand All @@ -53,20 +46,11 @@
import org.junit.gen5.engine.support.hierarchical.DummyTestEngine;
import org.junit.gen5.launcher.Launcher;
import org.opentest4j.AssertionFailedError;
import org.xml.sax.SAXException;

class XmlReportsWritingListenerTests {

private static Validator schemaValidator;
private Path tempDirectory;

@BeforeAll
static void initializeSchemaValidator() throws Exception {
URL schemaFile = XmlReportsWritingListener.class.getResource("/jenkins-junit.xsd");
SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
schemaValidator = schemaFactory.newSchema(schemaFile).newValidator();
}

@BeforeEach
void createTempDirectory(TestInfo testInfo) throws Exception {
tempDirectory = Files.createTempDirectory(testInfo.getName());
Expand Down Expand Up @@ -362,16 +346,7 @@ private String readValidXmlFile(String filename) throws Exception {
Path xmlFile = tempDirectory.resolve(filename);
assertTrue(Files.exists(xmlFile), () -> "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);
}
}
}

0 comments on commit 932c765

Please sign in to comment.