package org.springframework.load;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.text.DecimalFormat;
import java.util.Date;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Text;
/**
* XML reporter bean that writes an XML report and runs a stylesheet
* to generate a formatted file.
* @author Rod Johnson
*/
public class XmlTestReporter implements TestReporter {
private String xmlReportFileName;
private String stylesheet;
private String outputFile;
private DecimalFormat decimalFormat = (DecimalFormat) DecimalFormat.getInstance();
public XmlTestReporter() {
setDoubleFormat("###.##");
}
public final DecimalFormat getDecimalFormat() {
return this.decimalFormat;
}
/**
* Set the decimal format used to format doubles such as the
* number of hits per second
*/
public final void setDoubleFormat(String pattern) {
this.decimalFormat.applyPattern(pattern);
}
/**
* @see org.springframework.load.TestReporter#generateReport(AbstractTestSuite)
*/
public void generateReport(AbstractTestSuite suite) throws Exception {
try {
DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document doc = db.newDocument();
Element rootEle = doc.createElement("load-tests");
doc.appendChild(rootEle);
rootEle.setAttribute("date", new Date().toString());
addTestStatusAttributes(suite, rootEle);
rootEle.setAttribute("threads", "" + suite.getThreads());
// rootEle.setAttribute("fails", "" + suite.getf)
for (int i = 0; i < suite.getTests().length; i++) {
Test test = suite.getTests()[i];
Element testEle = doc.createElement("test");
rootEle.appendChild(testEle);
addTestStatusAttributes(test, testEle);
if (test.getFailureExceptions().length > 0) {
Element failuresEle = doc.createElement("failures");
testEle.appendChild(failuresEle);
for (int j = 0; j < test.getFailureExceptions().length; j++) {
Element failEle = doc.createElement("fail");
failuresEle.appendChild(failEle);
Text t = doc.createTextNode(test.getFailureExceptions()[j].getLocalizedMessage());
failEle.appendChild(t);
}
}
}
//String xmlstr = doc.getDocumentElement().toString();
//System.out.println(xmlstr);
System.out.println("Filename ='" + this.xmlReportFileName + "'");
//FileWriter fw = new FileWriter(this.fileName);
//fw.write(xmlstr);
FileOutputStream fos = new FileOutputStream(this.xmlReportFileName);
doTransform(new DOMSource(doc), fos, null);
fos.close();
System.out.println("Wrote XML report to '" + this.xmlReportFileName + "'");
if (this.stylesheet != null && this.outputFile != null) {
File f = new File(this.outputFile);
Source xml = new DOMSource(doc);
doTransform(xml, new FileOutputStream(f), new StreamSource(new FileInputStream(this.stylesheet)));
fos.close();
}
}
catch (Exception ex) {
throw new RuntimeException("XML failure " + ex);
}
}
private void addTestStatusAttributes(TestStatus test, Element testEle) {
testEle.setAttribute("completed", "" + test.isComplete());
testEle.setAttribute("passes", "" + test.getPasses());
testEle.setAttribute("name", "" + test.getName());
testEle.setAttribute("failures", "" + test.getErrorCount());
testEle.setAttribute("averageResponseTime", "" + test.getAverageResponseTime());
testEle.setAttribute("hitsPerSecond", this.decimalFormat.format(test.getTestsPerSecondCount()));
testEle.setAttribute("elapsedTime", "" + test.getElapsedTime());
testEle.setAttribute("pauseTime", "" + test.getTotalPauseTime());
testEle.setAttribute("totalWorkingTime", "" + test.getTotalWorkingTime());
testEle.setAttribute("class", test.getClass().getName());
}
private void doTransform(Source xml, OutputStream os, Source ss) throws Exception {
TransformerFactory tf = TransformerFactory.newInstance();
Transformer trans = (ss == null) ? tf.newTransformer() : tf.newTransformer(ss);
trans.setOutputProperty(OutputKeys.INDENT, "yes");
trans.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
trans.transform(xml, new StreamResult(os));
}
/**
* Returns the fileName.
* @return String
*/
public String getXmlReportFileName() {
return xmlReportFileName;
}
/**
* Sets the fileName.
* @param fileName The fileName to set
*/
public void setXmlReportFileName(String fileName) {
this.xmlReportFileName = fileName;
}
/**
* Returns the outputFile.
* @return String
*/
public String getOutputFile() {
return outputFile;
}
/**
* Returns the stylesheet.
* @return String
*/
public String getStylesheet() {
return stylesheet;
}
/**
* Sets the outputFile.
* @param outputFile The outputFile to set
*/
public void setOutputFile(String outputFile) {
this.outputFile = outputFile;
}
/**
* Sets the stylesheet.
* @param stylesheet The stylesheet to set
*/
public void setStylesheet(String stylesheet) {
this.stylesheet = stylesheet;
}
}