Java程序  |  200行  |  7.07 KB

/*
 * Copyright (C) 2009 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package vogar;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.TimeZone;
import org.kxml2.io.KXmlSerializer;


/**
 * Writes JUnit results to a series of XML files in a format consistent with
 * Ant's XMLJUnitResultFormatter.
 *
 * <p>Unlike Ant's formatter, this class does not report the execution time of
 * tests.
 *
 * TODO: unify this and com.google.coretests.XmlReportPrinter
 */
public class XmlReportPrinter {

    /** the XML namespace */
    private static final String ns = null;

    private final File directory;
    private final ExpectationStore expectationStore;
    private final Date date;

    public XmlReportPrinter(File directory, ExpectationStore expectationStore, Date date) {
        this.directory = directory;
        this.expectationStore = expectationStore;
        this.date = date;
    }

    /**
     * Returns true if this XML Report printer can be used to emit XML.
     */
    public boolean isReady() {
        return directory != null;
    }

    private String getGMTTimestamp() {
        SimpleDateFormat dateFormat = new SimpleDateFormat(XmlReportConstants.DATEFORMAT);
        TimeZone gmt = TimeZone.getTimeZone("GMT");
        dateFormat.setTimeZone(gmt);
        dateFormat.setLenient(true);
        return dateFormat.format(date);
    }

    /**
     * Populates the directory with the report data from the completed tests.
     */
    public int generateReports(Collection<Outcome> results) {
        Map<String, Suite> suites = testsToSuites(results);

        String timestamp = getGMTTimestamp();

        for (Suite suite : suites.values()) {
            String fileName = "TEST-" + suite.name + ".xml";
            suite.printReport(timestamp, fileName);
        }

        return suites.size();
    }

    private Map<String, Suite> testsToSuites(Collection<Outcome> outcomes) {
        Map<String, Suite> result = new LinkedHashMap<String, Suite>();
        for (Outcome outcome : outcomes) {
            if (outcome.getResult() == Result.UNSUPPORTED) {
                continue;
            }

            String suiteName = outcome.getSuiteName();
            Suite suite = result.get(suiteName);
            if (suite == null) {
                suite = new Suite(suiteName);
                result.put(suiteName, suite);
            }

            suite.outcomes.add(outcome);

            Expectation expectation = expectationStore.get(outcome);
            if (!expectation.matches(outcome)) {
                if (outcome.getResult() == Result.EXEC_FAILED) {
                    suite.failuresCount++;
                } else {
                    suite.errorsCount++;
                }
            }
        }
        return result;
    }

    class Suite {
        private final String name;
        private final List<Outcome> outcomes = new ArrayList<Outcome>();
        private int failuresCount;
        private int errorsCount;

        Suite(String name) {
            this.name = name;
        }

        private void print(KXmlSerializer serializer, String timestamp) throws IOException {
            serializer.startTag(ns, XmlReportConstants.TESTSUITE);
            serializer.attribute(ns, XmlReportConstants.ATTR_NAME, name);
            serializer.attribute(ns, XmlReportConstants.ATTR_TESTS, Integer.toString(outcomes.size()));
            serializer.attribute(ns, XmlReportConstants.ATTR_FAILURES, Integer.toString(failuresCount));
            serializer.attribute(ns, XmlReportConstants.ATTR_ERRORS, Integer.toString(errorsCount));
            serializer.attribute(ns, XmlReportConstants.ATTR_TIME, "0");
            serializer.attribute(ns, XmlReportConstants.TIMESTAMP, timestamp);
            serializer.attribute(ns, XmlReportConstants.HOSTNAME, "localhost");
            serializer.startTag(ns, XmlReportConstants.PROPERTIES);
            serializer.endTag(ns, XmlReportConstants.PROPERTIES);

            for (Outcome outcome : outcomes) {
                print(serializer, outcome);
            }

            serializer.endTag(ns, XmlReportConstants.TESTSUITE);
        }

        private void print(KXmlSerializer serializer, Outcome outcome) throws IOException {
            serializer.startTag(ns, XmlReportConstants.TESTCASE);
            serializer.attribute(ns, XmlReportConstants.ATTR_NAME, outcome.getTestName());
            serializer.attribute(ns, XmlReportConstants.ATTR_CLASSNAME, outcome.getSuiteName());
            serializer.attribute(ns, XmlReportConstants.ATTR_TIME, "0");

            Expectation expectation = expectationStore.get(outcome);
            if (!expectation.matches(outcome)) {
                String result;
                switch (outcome.getResult()) {
                    case EXEC_FAILED:
                        result = XmlReportConstants.FAILURE;
                        break;
                    case SUCCESS:
                        result = XmlReportConstants.SUCCESS;
                        break;
                    default:
                        result = XmlReportConstants.ERROR;
                        break;
                }
                serializer.startTag(ns, result);
                serializer.attribute(ns, XmlReportConstants.ATTR_TYPE, outcome.getResult().toString());
                String text = outcome.getOutput();
                serializer.text(text);
                serializer.endTag(ns, result);
            }

            serializer.endTag(ns, XmlReportConstants.TESTCASE);
        }

        void printReport(String timestamp, String fileName) {
            FileOutputStream stream = null;
            try {
                stream = new FileOutputStream(new File(directory, fileName));

                KXmlSerializer serializer = new KXmlSerializer();
                serializer.setOutput(stream, "UTF-8");
                serializer.startDocument("UTF-8", null);
                serializer.setFeature(
                        "http://xmlpull.org/v1/doc/features.html#indent-output", true);
                print(serializer, timestamp);
                serializer.endDocument();
            } catch (IOException e) {
                throw new RuntimeException(e);
            } finally {
                if (stream != null) {
                    try {
                        stream.close();
                    } catch (IOException ignored) {
                    }
                }
            }
        }
    }
}