A class which generates a single junit xml file. This file will be consumed by Polarion
This commit is contained in:
parent
7d444c8b13
commit
c874f96228
4 changed files with 313 additions and 2 deletions
|
@ -119,6 +119,7 @@
|
|||
|
||||
<modules>
|
||||
<module>test-apps</module>
|
||||
<module>test-utils</module>
|
||||
<module>servers</module>
|
||||
<module>tests</module>
|
||||
</modules>
|
||||
|
|
34
testsuite/integration-arquillian/test-utils/pom.xml
Normal file
34
testsuite/integration-arquillian/test-utils/pom.xml
Normal file
|
@ -0,0 +1,34 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>integration-arquillian</artifactId>
|
||||
<groupId>org.keycloak.testsuite</groupId>
|
||||
<version>2.2.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>integration-arquillian-test-utils</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>Test utils</name>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jboss.logging</groupId>
|
||||
<artifactId>jboss-logging</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-configuration</groupId>
|
||||
<artifactId>commons-configuration</artifactId>
|
||||
<version>1.10</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
|
@ -0,0 +1,269 @@
|
|||
package org.keycloak.testsuite.util.junit;
|
||||
|
||||
import org.apache.commons.configuration.PropertiesConfiguration;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import org.junit.Ignore;
|
||||
import org.junit.runner.Description;
|
||||
import org.junit.runner.Result;
|
||||
import org.junit.runner.notification.Failure;
|
||||
import org.junit.runner.notification.RunListener;
|
||||
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import javax.xml.transform.OutputKeys;
|
||||
import javax.xml.transform.Transformer;
|
||||
import javax.xml.transform.TransformerConfigurationException;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import javax.xml.transform.TransformerFactory;
|
||||
import javax.xml.transform.dom.DOMSource;
|
||||
import javax.xml.transform.stream.StreamResult;
|
||||
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.nio.charset.Charset;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
/**
|
||||
* Aggregates jUnit test results into a single report - XML file.
|
||||
*/
|
||||
public class AggregateResultsReporter extends RunListener {
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(AggregateResultsReporter.class);
|
||||
|
||||
private final Document xml;
|
||||
private final File reportFile;
|
||||
private final boolean working;
|
||||
|
||||
private final AtomicInteger tests = new AtomicInteger(0);
|
||||
private final AtomicInteger errors = new AtomicInteger(0);
|
||||
private final AtomicInteger failures = new AtomicInteger(0);
|
||||
private final AtomicInteger ignored = new AtomicInteger(0);
|
||||
private final AtomicLong suiteStartTime = new AtomicLong(0L);
|
||||
|
||||
private final AtomicReference<Element> testsuite = new AtomicReference<Element>();
|
||||
|
||||
private final Map<String, Long> testTimes = new HashMap<String, Long>();
|
||||
|
||||
public AggregateResultsReporter() {
|
||||
boolean working = true;
|
||||
Document xml = null;
|
||||
try {
|
||||
xml = createEmptyDocument();
|
||||
} catch (ParserConfigurationException ex) {
|
||||
LOGGER.error("Failed to create XML DOM - reporting will not be done", ex);
|
||||
working = false;
|
||||
}
|
||||
|
||||
File reportFile = null;
|
||||
try {
|
||||
reportFile = createReportFile();
|
||||
} catch (Exception ex) {
|
||||
LOGGER.error("Failed to create log file - reporting will not be done", ex);
|
||||
working = false;
|
||||
}
|
||||
|
||||
this.working = working;
|
||||
this.xml = xml;
|
||||
this.reportFile = reportFile;
|
||||
}
|
||||
|
||||
private Document createEmptyDocument() throws ParserConfigurationException {
|
||||
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
|
||||
return builder.newDocument();
|
||||
}
|
||||
|
||||
private File createReportFile() throws Exception {
|
||||
PropertiesConfiguration config = new PropertiesConfiguration(System.getProperty("testsuite.constants"));
|
||||
config.setThrowExceptionOnMissing(true);
|
||||
|
||||
final File logDir = new File(config.getString("log-dir"));
|
||||
logDir.mkdirs();
|
||||
|
||||
final File reportFile = new File(logDir, "junit-report.xml").getAbsoluteFile();
|
||||
reportFile.createNewFile();
|
||||
|
||||
return reportFile;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void testRunStarted(Description description) throws Exception {
|
||||
if (working) {
|
||||
suiteStartTime.set(System.currentTimeMillis());
|
||||
|
||||
Element testsuite = xml.createElement("testsuite");
|
||||
|
||||
if (description.getChildren().size() == 1) {
|
||||
testsuite.setAttribute("name", safeString(description.getChildren().get(0).getDisplayName()));
|
||||
}
|
||||
|
||||
xml.appendChild(testsuite);
|
||||
this.testsuite.set(testsuite);
|
||||
writeXml();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void testStarted(Description description) throws Exception {
|
||||
if (working) {
|
||||
testTimes.put(description.getDisplayName(), System.currentTimeMillis());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void testFinished(Description description) throws Exception {
|
||||
if (working) {
|
||||
if (testTimes.containsKey(description.getDisplayName())) {
|
||||
testsuite.get().appendChild(createTestCase(description));
|
||||
writeXml();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void testAssumptionFailure(Failure failure) {
|
||||
if (working) {
|
||||
ignored.incrementAndGet();
|
||||
|
||||
Element testcase = createTestCase(failure.getDescription());
|
||||
Element skipped = xml.createElement("skipped");
|
||||
skipped.setAttribute("message", safeString(failure.getMessage()));
|
||||
|
||||
testcase.appendChild(skipped);
|
||||
|
||||
testsuite.get().appendChild(testcase);
|
||||
writeXml();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void testFailure(Failure failure) throws Exception {
|
||||
if (working) {
|
||||
if (failure.getDescription().getMethodName() == null) {
|
||||
// before class failed
|
||||
for (Description child : failure.getDescription().getChildren()) {
|
||||
// mark all methods failed
|
||||
testFailure(new Failure(child, failure.getException()));
|
||||
}
|
||||
} else {
|
||||
// normal failure
|
||||
Element testcase = createTestCase(failure.getDescription());
|
||||
|
||||
Element element;
|
||||
if (failure.getException() instanceof AssertionError) {
|
||||
failures.incrementAndGet();
|
||||
element = xml.createElement("failure");
|
||||
} else {
|
||||
errors.incrementAndGet();
|
||||
element = xml.createElement("error");
|
||||
}
|
||||
|
||||
testcase.appendChild(element);
|
||||
|
||||
element.setAttribute("type", safeString(failure.getException().getClass().getName()));
|
||||
element.setAttribute("message", safeString(failure.getMessage()));
|
||||
element.appendChild(xml.createCDATASection(safeString(failure.getTrace())));
|
||||
|
||||
testsuite.get().appendChild(testcase);
|
||||
writeXml();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void testIgnored(Description description) throws Exception {
|
||||
if (working) {
|
||||
ignored.incrementAndGet();
|
||||
|
||||
Element testcase = createTestCase(description);
|
||||
|
||||
Element skipped = xml.createElement("skipped");
|
||||
skipped.setAttribute("message", safeString(description.getAnnotation(Ignore.class).value()));
|
||||
|
||||
testcase.appendChild(skipped);
|
||||
|
||||
testsuite.get().appendChild(testcase);
|
||||
writeXml();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void testRunFinished(Result result) throws Exception {
|
||||
if (working) {
|
||||
writeXml();
|
||||
}
|
||||
}
|
||||
|
||||
private void writeXml() {
|
||||
Element testsuite = this.testsuite.get();
|
||||
|
||||
testsuite.setAttribute("tests", Integer.toString(tests.get()));
|
||||
testsuite.setAttribute("errors", Integer.toString(errors.get()));
|
||||
testsuite.setAttribute("skipped", Integer.toString(ignored.get()));
|
||||
testsuite.setAttribute("failures", Integer.toString(failures.get()));
|
||||
testsuite.setAttribute("time", computeTestTime(suiteStartTime.get()));
|
||||
|
||||
try {
|
||||
Writer writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(reportFile, false), Charset.forName("UTF-8")));
|
||||
try {
|
||||
Transformer t = TransformerFactory.newInstance().newTransformer();
|
||||
t.setOutputProperty(OutputKeys.INDENT, "yes");
|
||||
t.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
|
||||
t.transform(new DOMSource(xml), new StreamResult(writer));
|
||||
} catch (TransformerConfigurationException ex) {
|
||||
LOGGER.error("Misconfigured transformer", ex);
|
||||
} catch (TransformerException ex) {
|
||||
LOGGER.error("Unable to save XML file", ex);
|
||||
} finally {
|
||||
writer.close();
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
LOGGER.warn("Unable to open report file", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private String computeTestTime(Long startTime) {
|
||||
if (startTime == null) {
|
||||
return "0";
|
||||
} else {
|
||||
long amount = System.currentTimeMillis() - startTime;
|
||||
return String.format("%.3f", amount / 1000F);
|
||||
}
|
||||
}
|
||||
|
||||
private Element createTestCase(Description description) {
|
||||
tests.incrementAndGet();
|
||||
|
||||
Element testcase = xml.createElement("testcase");
|
||||
|
||||
testcase.setAttribute("name", safeString(description.getMethodName()));
|
||||
testcase.setAttribute("classname", safeString(description.getClassName()));
|
||||
testcase.setAttribute("time", computeTestTime(testTimes.remove(description.getDisplayName())));
|
||||
|
||||
return testcase;
|
||||
}
|
||||
|
||||
private String safeString(String input) {
|
||||
if (input == null) {
|
||||
return "null";
|
||||
}
|
||||
|
||||
return input
|
||||
// first remove color coding (all of it)
|
||||
.replaceAll("\u001b\\[\\d+m", "")
|
||||
// then remove control characters that are not whitespaces
|
||||
.replaceAll("[\\p{Cntrl}&&[^\\p{Space}]]", "");
|
||||
}
|
||||
}
|
|
@ -37,7 +37,7 @@
|
|||
<module>base</module>
|
||||
<module>other</module>
|
||||
</modules>
|
||||
|
||||
|
||||
<properties>
|
||||
<auth.server>undertow</auth.server>
|
||||
<auth.server.undertow>true</auth.server.undertow>
|
||||
|
@ -178,7 +178,7 @@
|
|||
<properties>
|
||||
<property>
|
||||
<name>listener</name>
|
||||
<value>org.keycloak.testsuite.util.TestEventsLogger</value>
|
||||
<value>org.keycloak.testsuite.util.TestEventsLogger,org.keycloak.testsuite.util.junit.AggregateResultsReporter</value>
|
||||
</property>
|
||||
</properties>
|
||||
</configuration>
|
||||
|
@ -645,6 +645,13 @@
|
|||
</file>
|
||||
</activation>
|
||||
<dependencies>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.keycloak.testsuite</groupId>
|
||||
<artifactId>integration-arquillian-test-utils</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- TEST DEPENDENCIES -->
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
|
|
Loading…
Reference in a new issue