blob: a6080724bcbfc5aab3fff87990fdfcc324f62014 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 org.apache.royale.test.ant.report;
import java.io.File;
import java.io.FileOutputStream;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.util.DateUtils;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.XMLWriter;
import org.apache.royale.test.ant.LoggingUtil;
public class Report
{
private static final String FAILURE = "failure";
private static final String ERROR = "error";
private static final String IGNORE = "ignore";
private static final String TEST_SUITE = "testsuite";
private static final String NAME_ATTRIBUTE_LABEL = "name";
private static final String FAILURE_ATTRIBUTE_LABEL = "failures";
private static final String ERROR_ATTRIBUTE_LABEL = "errors";
private static final String IGNORE_ATTRIBUTE_LABEL = "skipped";
private static final String TIME_ATTRIBUTE_LABEL = "time";
private static final String TESTS_ATTRIBUTE_LABEL = "tests";
private static final String HOSTNAME_ATTRIBUTE_LABEL = "hostname";
private static final String TIMESTAMP_ATTRIBUTE_LABEL = "timestamp";
private static final String FILENAME_PREFIX = "TEST-";
private static final String FILENAME_EXTENSION = ".xml";
// Exception messages
private static final String FAILED_TEST = "RoyaleUnit test {0} in suite {1} failed.";
private static final String ERRORED_TEST = "RoyaleUnit test {0} in suite {1} had errors.";
private static final String IGNORED_TEST = "RoyaleUnit test {0} in suite {1} was ignored.";
private static final String TEST_INFO = "Suite: {0}\nTests run: {1}, Failures: {2}, Errors: {3}, Skipped: {4}, Time elapsed: {5} sec";
private static final String ERROR_SAVING_REPORT = "Error saving report.";
// XML attribute labels
private static final String CLASSNAME_ATTRIBUTE = "classname";
private static final String NAME_ATTRIBUTE = "name";
private static final String STATUS_ATTRIBUTE = "status";
private static final String TIME_ATTRIBUTE = "time";
protected Suite suite;
private Document document;
private List<String> recordedRuns;
public Report(Suite suite)
{
this.recordedRuns = new ArrayList<String>();
this.suite = suite;
// Create a new XML document
document = DocumentHelper.createDocument();
// Add the test suite attributes to the document
document
.addElement(TEST_SUITE)
.addAttribute(NAME_ATTRIBUTE_LABEL, suite.getName())
.addAttribute(TESTS_ATTRIBUTE_LABEL,
String.valueOf(suite.getTests()))
.addAttribute(FAILURE_ATTRIBUTE_LABEL,
String.valueOf(suite.getFailures()))
.addAttribute(ERROR_ATTRIBUTE_LABEL,
String.valueOf(suite.getErrors()))
.addAttribute(IGNORE_ATTRIBUTE_LABEL,
String.valueOf(suite.getSkips()))
.addAttribute(TIME_ATTRIBUTE_LABEL, String.valueOf(suite.getTime()));
}
/**
* Adds the test to the suite report given an XML test document
*/
public void addTest(Document test)
{
Element root = test.getRootElement();
// Add to the number of tests in this suite if not seen and not null
String testMethod = root.attributeValue(NAME_ATTRIBUTE);
if(!recordedRuns.contains(testMethod) && !testMethod.equals("null"))
{
recordedRuns.add(testMethod);
suite.addTest();
}
//add test time to total time
long time = Long.parseLong(root.attributeValue(TIME_ATTRIBUTE));
suite.addTime(time);
root.attribute(TIME_ATTRIBUTE).setText(formatTime(time));
//If the test method name is null, then make it the classname
if(root.attributeValue(NAME_ATTRIBUTE).equals("null"))
{
root.attribute(NAME_ATTRIBUTE).setText(root.attributeValue(CLASSNAME_ATTRIBUTE));
}
// Add the test to the report document
document.getRootElement().add(root);
// Check for special status adjustments to make to suite
checkForStatus(test);
//remove status attribute since it's only used by the report
root.remove(root.attribute(STATUS_ATTRIBUTE));
}
private String formatTime(long time)
{
return String.format("%.3f", new Double(time / 1000.0000));
}
/**
* Updates counts for failed, error, and ignore on suite as well as logs what
* failed if told to use logging.
*
* @param test
* Test XML document
*/
private void checkForStatus(Document test)
{
// Get the root element and pull the test name and status
final Element root = test.getRootElement();
final String name = root.attributeValue(NAME_ATTRIBUTE);
final String status = root.attributeValue(STATUS_ATTRIBUTE);
String format = null;
if (status.equals(FAILURE))
{
format = FAILED_TEST;
suite.addFailure();
}
else if (status.equals(ERROR))
{
format = ERRORED_TEST;
suite.addError();
}
else if (status.equals(IGNORE))
{
format = IGNORED_TEST;
suite.addSkip();
}
// Creates the fail message for use with verbose
if (format != null)
{
final String message = MessageFormat.format(format, new Object[]
{ name, suite });
LoggingUtil.log(message);
}
}
/**
* Determines if any failures (errors or failures) have occurred in this
* report.
*/
public boolean hasFailures()
{
return (suite.getErrors() > 0 || suite.getFailures() > 0);
}
/**
* Write the report XML document out to file
*
* @param reportDir
* Directory to hold report file.
*/
public void save(File reportDir) throws BuildException
{
try
{
// Open the file matching the parameter suite
final File file = new File(reportDir, FILENAME_PREFIX + suite + FILENAME_EXTENSION);
// Retrieve the root element and adjust the failures and test attributes
Element root = document.getRootElement();
root.addAttribute(FAILURE_ATTRIBUTE_LABEL, String.valueOf(suite.getFailures()));
root.addAttribute(ERROR_ATTRIBUTE_LABEL, String.valueOf(suite.getErrors()));
root.addAttribute(TESTS_ATTRIBUTE_LABEL, String.valueOf(suite.getTests()));
root.addAttribute(IGNORE_ATTRIBUTE_LABEL, String.valueOf(suite.getSkips()));
root.addAttribute(TIME_ATTRIBUTE_LABEL, String.valueOf(formatTime(suite.getTime())));
root.addAttribute(HOSTNAME_ATTRIBUTE_LABEL, getHostname());
final String timestamp = DateUtils.format(new Date(), DateUtils.ISO8601_DATETIME_PATTERN);
root.addAttribute(TIMESTAMP_ATTRIBUTE_LABEL, timestamp);
// Write the updated suite
final OutputFormat format = OutputFormat.createPrettyPrint();
final XMLWriter writer = new XMLWriter(new FileOutputStream(file), format);
writer.write(document);
writer.close();
}
catch (Exception e)
{
throw new BuildException(ERROR_SAVING_REPORT, e);
}
}
private String getHostname()
{
try
{
return InetAddress.getLocalHost().getHostName();
} catch (UnknownHostException e)
{
return "localhost";
}
}
public String getSummary()
{
String summary = "";
try
{
summary = MessageFormat.format(TEST_INFO, new Object[]
{ new String(suite.getName()), new Integer(suite.getTests()),
new Integer(suite.getFailures()),
new Integer(suite.getErrors()), new Integer(suite.getSkips()),
formatTime(suite.getTime()) });
} catch (Exception e)
{
// ignore
}
return summary;
}
}