All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.cucumber.junitxmlformatter.XmlReportWriter Maven / Gradle / Ivy

The newest version!
package io.cucumber.junitxmlformatter;

import io.cucumber.messages.types.Exception;
import io.cucumber.messages.types.TestCaseStarted;
import io.cucumber.messages.types.TestStepResult;
import io.cucumber.messages.types.TestStepResultStatus;

import java.util.List;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamException;
import java.io.Writer;
import java.text.NumberFormat;
import java.util.EnumSet;
import java.util.Locale;
import java.util.Map;
import java.util.Optional;

import static io.cucumber.messages.types.TestStepResultStatus.PASSED;
import static io.cucumber.messages.types.TestStepResultStatus.SKIPPED;

class XmlReportWriter {
    private final NumberFormat numberFormat = NumberFormat.getInstance(Locale.US);
    private final XmlReportData data;

    XmlReportWriter(XmlReportData data) {
        this.data = data;
    }

    void writeXmlReport(Writer out) throws XMLStreamException {
        XMLOutputFactory factory = XMLOutputFactory.newInstance();
        EscapingXmlStreamWriter writer = new EscapingXmlStreamWriter(factory.createXMLStreamWriter(out));
        writer.writeStartDocument("UTF-8", "1.0");
        writer.writeNewLine();
        writeTestsuite(writer);
        writer.writeEndDocument();
        writer.flush();
    }

    private void writeTestsuite(EscapingXmlStreamWriter writer) throws XMLStreamException {
        writer.writeStartElement("testsuite");
        writeSuiteAttributes(writer);
        writer.writeNewLine();

        for (TestCaseStarted testCaseStarted : data.getAllTestCaseStarted()) {
            writeTestcase(writer, testCaseStarted);
        }

        writer.writeEndElement();
        writer.writeNewLine();
    }

    private void writeSuiteAttributes(EscapingXmlStreamWriter writer) throws XMLStreamException {
        writer.writeAttribute("name", "Cucumber");
        writer.writeAttribute("time", numberFormat.format(data.getSuiteDurationInSeconds()));

        Map counts = data.getTestCaseStatusCounts();

        writer.writeAttribute("tests", String.valueOf(data.getTestCaseCount()));
        writer.writeAttribute("skipped", counts.get(SKIPPED).toString());
        writer.writeAttribute("failures", String.valueOf(countFailures(counts)));
        writer.writeAttribute("errors", "0");

        Optional testRunStartedAt = data.getTestRunStartedAt();
        if (testRunStartedAt.isPresent()) {
            writer.writeAttribute("timestamp", testRunStartedAt.get());
        }
    }

    private static long countFailures(Map counts) {
        return createNotPassedNotSkippedSet().stream().mapToLong(counts::get).sum();
    }

    private static EnumSet createNotPassedNotSkippedSet() {
        EnumSet notPassedNotSkipped = EnumSet.allOf(TestStepResultStatus.class);
        notPassedNotSkipped.remove(PASSED);
        notPassedNotSkipped.remove(SKIPPED);
        return notPassedNotSkipped;
    }

    private void writeTestcase(EscapingXmlStreamWriter writer, TestCaseStarted testCaseStarted) throws XMLStreamException {
        writer.writeStartElement("testcase");
        writeTestCaseAttributes(writer, testCaseStarted);
        writer.writeNewLine();
        writeNonPassedElement(writer, testCaseStarted);
        writeStepAndResultList(writer, testCaseStarted);
        writer.writeEndElement();
        writer.writeNewLine();
    }

    private void writeTestCaseAttributes(EscapingXmlStreamWriter writer, TestCaseStarted testCaseStarted) throws XMLStreamException {
        writer.writeAttribute("classname", data.getFeatureName(testCaseStarted));
        writer.writeAttribute("name", data.getPickleName(testCaseStarted));
        writer.writeAttribute("time", numberFormat.format(data.getDurationInSeconds(testCaseStarted)));
    }

    private void writeNonPassedElement(EscapingXmlStreamWriter writer, TestCaseStarted testCaseStarted) throws XMLStreamException {
        TestStepResult result = data.getTestCaseStatus(testCaseStarted);
        TestStepResultStatus status = result.getStatus();
        if (status == TestStepResultStatus.PASSED) {
            return;
        }

        String elementName = status == SKIPPED ? "skipped" : "failure";

        Optional message = result.getMessage();
        Optional exceptionType = result.getException().map(Exception::getType);
        Optional exceptionMessage = result.getException().flatMap(Exception::getMessage);
        Optional exceptionStackTrace = result.getException().flatMap(Exception::getStackTrace);

        boolean hasMessageOrStackTrace = message.isPresent() || exceptionStackTrace.isPresent();
        if (hasMessageOrStackTrace) {
            writer.writeStartElement(elementName);
        } else {
            writer.writeEmptyElement(elementName);
        }

        if (status != SKIPPED && exceptionType.isPresent()) {
            writer.writeAttribute("type", exceptionType.get());
        }
        if (exceptionMessage.isPresent()) {
            writer.writeAttribute("message", exceptionMessage.get());
        }
        if (hasMessageOrStackTrace) {
            if (exceptionStackTrace.isPresent()) {
                writer.writeNewLine();
                writer.writeCData(exceptionStackTrace.get());
                writer.writeNewLine();
            } else {
                // Fall back to message for older implementations
                // that put the stack trace in the message
                writer.writeNewLine();
                writer.writeCData(message.get());
                writer.writeNewLine();
            }
        }

        if (hasMessageOrStackTrace) {
            writer.writeEndElement();
        }
        writer.writeNewLine();
    }

    private void writeStepAndResultList(EscapingXmlStreamWriter writer, TestCaseStarted testCaseStarted) throws XMLStreamException {
        List> results = data.getStepsAndResult(testCaseStarted);
        if (results.isEmpty()) {
            return;
        }
        writer.writeStartElement("system-out");
        writer.writeCData(createStepResultList(results));
        writer.writeEndElement();
        writer.writeNewLine();
    }

    private static String createStepResultList(List> results) {
        StringBuilder sb = new StringBuilder();
        sb.append("\n");
        results.forEach(r -> {
            String stepText = r.getKey();
            String status = r.getValue();
            sb.append(stepText);
            sb.append(".");
            for (int i = 75 - stepText.length(); i > 0; i--) {
                sb.append(".");
            }
            sb.append(status);
            sb.append("\n");
        });
        return sb.toString();
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy