Updated Branches: refs/heads/master 5bfd27173 -> 14f8995d5
o Added more tests, preparing for XmlWriter impl Project: http://git-wip-us.apache.org/repos/asf/maven-surefire/repo Commit: http://git-wip-us.apache.org/repos/asf/maven-surefire/commit/14f8995d Tree: http://git-wip-us.apache.org/repos/asf/maven-surefire/tree/14f8995d Diff: http://git-wip-us.apache.org/repos/asf/maven-surefire/diff/14f8995d Branch: refs/heads/master Commit: 14f8995d5152e829de4e33afa4b2b2e1b9002ad6 Parents: 5bfd271 Author: Kristian Rosenvold <krosenv...@apache.org> Authored: Wed Jan 2 13:48:31 2013 +0100 Committer: Kristian Rosenvold <krosenv...@apache.org> Committed: Wed Jan 2 13:52:23 2013 +0100 ---------------------------------------------------------------------- .../surefire/report/StatelessXmlReporter.java | 608 +++++++------- .../surefire/report/StatelessXmlReporter2.java | 304 +++++++ .../maven/surefire/report/RunStatistics.java | 290 ++++---- .../surefire/report/StatelessXMLReporterTest.java | 64 ++- 4 files changed, 816 insertions(+), 450 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/14f8995d/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/StatelessXmlReporter.java ---------------------------------------------------------------------- diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/StatelessXmlReporter.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/StatelessXmlReporter.java index c306b1d..680a21d 100644 --- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/StatelessXmlReporter.java +++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/StatelessXmlReporter.java @@ -1,304 +1,304 @@ -package org.apache.maven.plugin.surefire.report; - -/* - * 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. - */ - -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.OutputStreamWriter; -import java.io.PrintWriter; -import java.io.UnsupportedEncodingException; -import java.util.Enumeration; -import java.util.Properties; -import java.util.StringTokenizer; -import org.apache.maven.shared.utils.io.IOUtil; -import org.apache.maven.shared.utils.xml.Xpp3Dom; -import org.apache.maven.shared.utils.xml.Xpp3DomWriter; -import org.apache.maven.surefire.report.ReportEntry; -import org.apache.maven.surefire.report.ReporterException; -import org.apache.maven.surefire.report.SafeThrowable; - -/** - * XML format reporter writing to <code>TEST-<i>reportName</i>[-<i>suffix</i>].xml</code> file like written and read - * by Ant's <a href="http://ant.apache.org/manual/Tasks/junit.html"><code><junit></code></a> and - * <a href="http://ant.apache.org/manual/Tasks/junitreport.html"><code><junitreport></code></a> tasks, - * then supported by many tools like CI servers. - * <p/> - * <pre><?xml version="1.0" encoding="UTF-8"?> - * <testsuite name="<i>suite name</i>" [group="<i>group</i>"] tests="<i>0</i>" failures="<i>0</i>" errors="<i>0</i>" skipped="<i>0</i>" time="<i>0,###.###</i>"> - * <properties> - * <property name="<i>name</i>" value="<i>value</i>"/> - * [...] - * </properties> - * <testcase time="<i>0,###.###</i>" name="<i>test name</i> [classname="<i>class name</i>"] [group="<i>group</i>"]"/> - * <testcase time="<i>0,###.###</i>" name="<i>test name</i> [classname="<i>class name</i>"] [group="<i>group</i>"]"> - * <<b>error</b> message="<i>message</i>" type="<i>exception class name</i>"><i>stacktrace</i></error> - * <system-out><i>system out content (present only if not empty)</i></system-out> - * <system-err><i>system err content (present only if not empty)</i></system-err> - * </testcase> - * <testcase time="<i>0,###.###</i>" name="<i>test name</i> [classname="<i>class name</i>"] [group="<i>group</i>"]"> - * <<b>failure</b> message="<i>message</i>" type="<i>exception class name</i>"><i>stacktrace</i></failure> - * <system-out><i>system out content (present only if not empty)</i></system-out> - * <system-err><i>system err content (present only if not empty)</i></system-err> - * </testcase> - * <testcase time="<i>0,###.###</i>" name="<i>test name</i> [classname="<i>class name</i>"] [group="<i>group</i>"]"> - * <<b>skipped</b>/> - * </testcase> - * [...]</pre> - * - * @author <a href="mailto:jr...@exist.com">Johnny R. Ruiz III</a> - * @author Kristian Rosenvold - * @see <a href="http://wiki.apache.org/ant/Proposals/EnhancedTestReports">Ant's format enhancement proposal</a> - * (not yet implemented by Ant 1.8.2) - */ -public class StatelessXmlReporter -{ - private static final String LS = System.getProperty( "line.separator" ); - - private final File reportsDirectory; - - private final String reportNameSuffix; - - private final boolean trimStackTrace; - - public StatelessXmlReporter( File reportsDirectory, String reportNameSuffix, boolean trimStackTrace ) - { - this.reportsDirectory = reportsDirectory; - this.reportNameSuffix = reportNameSuffix; - this.trimStackTrace = trimStackTrace; - } - - public void testSetCompleted( WrappedReportEntry testSetReportEntry, TestSetStats testSetStats ) - throws ReporterException - { - - Xpp3Dom testSuite = createTestSuiteElement( testSetReportEntry, testSetStats, reportNameSuffix ); - - showProperties( testSuite ); - - testSuite.setAttribute( "tests", String.valueOf( testSetStats.getCompletedCount() ) ); - - testSuite.setAttribute( "errors", String.valueOf( testSetStats.getErrors() ) ); - - testSuite.setAttribute( "skipped", String.valueOf( testSetStats.getSkipped() ) ); - - testSuite.setAttribute( "failures", String.valueOf( testSetStats.getFailures() ) ); - - for ( WrappedReportEntry entry : testSetStats.getReportEntries() ) - { - if ( ReportEntryType.success.equals( entry.getReportEntryType() ) ) - { - testSuite.addChild( createTestElement( entry, reportNameSuffix ) ); - } - else - { - testSuite.addChild( getTestProblems( entry, trimStackTrace, reportNameSuffix ) ); - } - - } - - File reportFile = getReportFile( testSetReportEntry, reportsDirectory, reportNameSuffix ); - - File reportDir = reportFile.getParentFile(); - - //noinspection ResultOfMethodCallIgnored - reportDir.mkdirs(); - - PrintWriter writer = null; - - try - { - writer = new PrintWriter( - new BufferedWriter( new OutputStreamWriter( new FileOutputStream( reportFile ), "UTF-8" ) ) ); - - writer.write( "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>" + LS ); - - Xpp3DomWriter.write( new PrettyPrintXMLWriter( writer ), testSuite ); - } - catch ( UnsupportedEncodingException e ) - { - throw new ReporterException( "Unable to use UTF-8 encoding", e ); - } - catch ( FileNotFoundException e ) - { - throw new ReporterException( "Unable to create file: " + e.getMessage(), e ); - } - - finally - { - IOUtil.close( writer ); - } - } - - private File getReportFile( ReportEntry report, File reportsDirectory, String reportNameSuffix ) - { - File reportFile; - - if ( reportNameSuffix != null && reportNameSuffix.length() > 0 ) - { - reportFile = new File( reportsDirectory, "TEST-" + report.getName() + "-" + reportNameSuffix + ".xml" ); - } - else - { - reportFile = new File( reportsDirectory, "TEST-" + report.getName() + ".xml" ); - } - - return reportFile; - } - - private static Xpp3Dom createTestElement( WrappedReportEntry report, String reportNameSuffix ) - { - Xpp3Dom testCase = new Xpp3Dom( "testcase" ); - testCase.setAttribute( "name", report.getReportName() ); - if ( report.getGroup() != null ) - { - testCase.setAttribute( "group", report.getGroup() ); - } - if ( report.getSourceName() != null ) - { - if ( reportNameSuffix != null && reportNameSuffix.length() > 0 ) - { - testCase.setAttribute( "classname", report.getSourceName() + "(" + reportNameSuffix + ")" ); - } - else - { - testCase.setAttribute( "classname", report.getSourceName() ); - } - } - testCase.setAttribute( "time", report.elapsedTimeAsString() ); - return testCase; - } - - private static Xpp3Dom createTestSuiteElement( WrappedReportEntry report, TestSetStats testSetStats, - String reportNameSuffix1 ) - { - Xpp3Dom testCase = new Xpp3Dom( "testsuite" ); - - testCase.setAttribute( "name", report.getReportName( reportNameSuffix1 ) ); - - if ( report.getGroup() != null ) - { - testCase.setAttribute( "group", report.getGroup() ); - } - testCase.setAttribute( "time", testSetStats.getElapsedForTestSet() ); - return testCase; - } - - - private Xpp3Dom getTestProblems( WrappedReportEntry report, boolean trimStackTrace, String reportNameSuffix ) - { - - Xpp3Dom testCase = createTestElement( report, reportNameSuffix ); - - Xpp3Dom element = createElement( testCase, report.getReportEntryType().name() ); - - String stackTrace = report.getStackTrace( trimStackTrace ); - - if ( report.getMessage() != null && report.getMessage().length() > 0 ) - { - element.setAttribute( "message", report.getMessage() ); - } - - if ( report.getStackTraceWriter() != null ) - { - //noinspection ThrowableResultOfMethodCallIgnored - SafeThrowable t = report.getStackTraceWriter().getThrowable(); - if ( t != null ) - { - if ( t.getMessage() != null ) - { - element.setAttribute( "type", ( stackTrace.contains( ":" ) - ? stackTrace.substring( 0, stackTrace.indexOf( ":" ) ) - : stackTrace ) ); - } - else - { - element.setAttribute( "type", new StringTokenizer( stackTrace ).nextToken() ); - } - } - } - - if ( stackTrace != null ) - { - element.setValue( stackTrace ); - } - - addOutputStreamElement( report.getStdout(), "system-out", testCase ); - - addOutputStreamElement( report.getStdErr(), "system-err", testCase ); - - return testCase; - } - - private void addOutputStreamElement( String stdOut, String name, Xpp3Dom testCase ) - { - if ( stdOut != null && stdOut.trim().length() > 0 ) - { - createElement( testCase, name ).setValue( stdOut ); - } - } - - private Xpp3Dom createElement( Xpp3Dom element, String name ) - { - Xpp3Dom component = new Xpp3Dom( name ); - - element.addChild( component ); - - return component; - } - - /** - * Adds system properties to the XML report. - * <p/> - * - * @param testSuite The test suite to report to - */ - private void showProperties( Xpp3Dom testSuite ) - { - Xpp3Dom properties = createElement( testSuite, "properties" ); - - Properties systemProperties = System.getProperties(); - - if ( systemProperties != null ) - { - Enumeration<?> propertyKeys = systemProperties.propertyNames(); - - while ( propertyKeys.hasMoreElements() ) - { - String key = (String) propertyKeys.nextElement(); - - String value = systemProperties.getProperty( key ); - - if ( value == null ) - { - value = "null"; - } - - Xpp3Dom property = createElement( properties, "property" ); - - property.setAttribute( "name", key ); - - property.setAttribute( "value", value ); - - } - } - } -} +package org.apache.maven.plugin.surefire.report; + +/* + * 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. + */ + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.OutputStreamWriter; +import java.io.PrintWriter; +import java.io.UnsupportedEncodingException; +import java.util.Enumeration; +import java.util.Properties; +import java.util.StringTokenizer; +import org.apache.maven.shared.utils.io.IOUtil; +import org.apache.maven.shared.utils.xml.Xpp3Dom; +import org.apache.maven.shared.utils.xml.Xpp3DomWriter; +import org.apache.maven.surefire.report.ReportEntry; +import org.apache.maven.surefire.report.ReporterException; +import org.apache.maven.surefire.report.SafeThrowable; + +/** + * XML format reporter writing to <code>TEST-<i>reportName</i>[-<i>suffix</i>].xml</code> file like written and read + * by Ant's <a href="http://ant.apache.org/manual/Tasks/junit.html"><code><junit></code></a> and + * <a href="http://ant.apache.org/manual/Tasks/junitreport.html"><code><junitreport></code></a> tasks, + * then supported by many tools like CI servers. + * <p/> + * <pre><?xml version="1.0" encoding="UTF-8"?> + * <testsuite name="<i>suite name</i>" [group="<i>group</i>"] tests="<i>0</i>" failures="<i>0</i>" errors="<i>0</i>" skipped="<i>0</i>" time="<i>0,###.###</i>"> + * <properties> + * <property name="<i>name</i>" value="<i>value</i>"/> + * [...] + * </properties> + * <testcase time="<i>0,###.###</i>" name="<i>test name</i> [classname="<i>class name</i>"] [group="<i>group</i>"]"/> + * <testcase time="<i>0,###.###</i>" name="<i>test name</i> [classname="<i>class name</i>"] [group="<i>group</i>"]"> + * <<b>error</b> message="<i>message</i>" type="<i>exception class name</i>"><i>stacktrace</i></error> + * <system-out><i>system out content (present only if not empty)</i></system-out> + * <system-err><i>system err content (present only if not empty)</i></system-err> + * </testcase> + * <testcase time="<i>0,###.###</i>" name="<i>test name</i> [classname="<i>class name</i>"] [group="<i>group</i>"]"> + * <<b>failure</b> message="<i>message</i>" type="<i>exception class name</i>"><i>stacktrace</i></failure> + * <system-out><i>system out content (present only if not empty)</i></system-out> + * <system-err><i>system err content (present only if not empty)</i></system-err> + * </testcase> + * <testcase time="<i>0,###.###</i>" name="<i>test name</i> [classname="<i>class name</i>"] [group="<i>group</i>"]"> + * <<b>skipped</b>/> + * </testcase> + * [...]</pre> + * + * @author <a href="mailto:jr...@exist.com">Johnny R. Ruiz III</a> + * @author Kristian Rosenvold + * @see <a href="http://wiki.apache.org/ant/Proposals/EnhancedTestReports">Ant's format enhancement proposal</a> + * (not yet implemented by Ant 1.8.2) + */ +public class StatelessXmlReporter +{ + private static final String LS = System.getProperty( "line.separator" ); + + private final File reportsDirectory; + + private final String reportNameSuffix; + + private final boolean trimStackTrace; + + public StatelessXmlReporter( File reportsDirectory, String reportNameSuffix, boolean trimStackTrace ) + { + this.reportsDirectory = reportsDirectory; + this.reportNameSuffix = reportNameSuffix; + this.trimStackTrace = trimStackTrace; + } + + public void testSetCompleted( WrappedReportEntry testSetReportEntry, TestSetStats testSetStats ) + throws ReporterException + { + + Xpp3Dom testSuite = createTestSuiteElement( testSetReportEntry, testSetStats, reportNameSuffix ); + + showProperties( testSuite ); + + testSuite.setAttribute( "tests", String.valueOf( testSetStats.getCompletedCount() ) ); + + testSuite.setAttribute( "errors", String.valueOf( testSetStats.getErrors() ) ); + + testSuite.setAttribute( "skipped", String.valueOf( testSetStats.getSkipped() ) ); + + testSuite.setAttribute( "failures", String.valueOf( testSetStats.getFailures() ) ); + + for ( WrappedReportEntry entry : testSetStats.getReportEntries() ) + { + if ( ReportEntryType.success.equals( entry.getReportEntryType() ) ) + { + testSuite.addChild( createTestElement( entry, reportNameSuffix ) ); + } + else + { + testSuite.addChild( getTestProblems( entry, trimStackTrace, reportNameSuffix ) ); + } + + } + + File reportFile = getReportFile( testSetReportEntry, reportsDirectory, reportNameSuffix ); + + File reportDir = reportFile.getParentFile(); + + //noinspection ResultOfMethodCallIgnored + reportDir.mkdirs(); + + PrintWriter writer = null; + + try + { + writer = new PrintWriter( + new BufferedWriter( new OutputStreamWriter( new FileOutputStream( reportFile ), "UTF-8" ) ) ); + + writer.write( "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + LS ); + + Xpp3DomWriter.write( new PrettyPrintXMLWriter( writer ), testSuite ); + } + catch ( UnsupportedEncodingException e ) + { + throw new ReporterException( "Unable to use UTF-8 encoding", e ); + } + catch ( FileNotFoundException e ) + { + throw new ReporterException( "Unable to create file: " + e.getMessage(), e ); + } + + finally + { + IOUtil.close( writer ); + } + } + + private File getReportFile( ReportEntry report, File reportsDirectory, String reportNameSuffix ) + { + File reportFile; + + if ( reportNameSuffix != null && reportNameSuffix.length() > 0 ) + { + reportFile = new File( reportsDirectory, "TEST-" + report.getName() + "-" + reportNameSuffix + ".xml" ); + } + else + { + reportFile = new File( reportsDirectory, "TEST-" + report.getName() + ".xml" ); + } + + return reportFile; + } + + private static Xpp3Dom createTestElement( WrappedReportEntry report, String reportNameSuffix ) + { + Xpp3Dom testCase = new Xpp3Dom( "testcase" ); + testCase.setAttribute( "name", report.getReportName() ); + if ( report.getGroup() != null ) + { + testCase.setAttribute( "group", report.getGroup() ); + } + if ( report.getSourceName() != null ) + { + if ( reportNameSuffix != null && reportNameSuffix.length() > 0 ) + { + testCase.setAttribute( "classname", report.getSourceName() + "(" + reportNameSuffix + ")" ); + } + else + { + testCase.setAttribute( "classname", report.getSourceName() ); + } + } + testCase.setAttribute( "time", report.elapsedTimeAsString() ); + return testCase; + } + + private static Xpp3Dom createTestSuiteElement( WrappedReportEntry report, TestSetStats testSetStats, + String reportNameSuffix1 ) + { + Xpp3Dom testCase = new Xpp3Dom( "testsuite" ); + + testCase.setAttribute( "name", report.getReportName( reportNameSuffix1 ) ); + + if ( report.getGroup() != null ) + { + testCase.setAttribute( "group", report.getGroup() ); + } + testCase.setAttribute( "time", testSetStats.getElapsedForTestSet() ); + return testCase; + } + + + private Xpp3Dom getTestProblems( WrappedReportEntry report, boolean trimStackTrace, String reportNameSuffix ) + { + + Xpp3Dom testCase = createTestElement( report, reportNameSuffix ); + + Xpp3Dom element = createElement( testCase, report.getReportEntryType().name() ); + + String stackTrace = report.getStackTrace( trimStackTrace ); + + if ( report.getMessage() != null && report.getMessage().length() > 0 ) + { + element.setAttribute( "message", report.getMessage() ); + } + + if ( report.getStackTraceWriter() != null ) + { + //noinspection ThrowableResultOfMethodCallIgnored + SafeThrowable t = report.getStackTraceWriter().getThrowable(); + if ( t != null ) + { + if ( t.getMessage() != null ) + { + element.setAttribute( "type", ( stackTrace.contains( ":" ) + ? stackTrace.substring( 0, stackTrace.indexOf( ":" ) ) + : stackTrace ) ); + } + else + { + element.setAttribute( "type", new StringTokenizer( stackTrace ).nextToken() ); + } + } + } + + if ( stackTrace != null ) + { + element.setValue( stackTrace ); + } + + addOutputStreamElement( report.getStdout(), "system-out", testCase ); + + addOutputStreamElement( report.getStdErr(), "system-err", testCase ); + + return testCase; + } + + private void addOutputStreamElement( String stdOut, String name, Xpp3Dom testCase ) + { + if ( stdOut != null && stdOut.trim().length() > 0 ) + { + createElement( testCase, name ).setValue( stdOut ); + } + } + + private Xpp3Dom createElement( Xpp3Dom element, String name ) + { + Xpp3Dom component = new Xpp3Dom( name ); + + element.addChild( component ); + + return component; + } + + /** + * Adds system properties to the XML report. + * <p/> + * + * @param testSuite The test suite to report to + */ + private void showProperties( Xpp3Dom testSuite ) + { + Xpp3Dom properties = createElement( testSuite, "properties" ); + + Properties systemProperties = System.getProperties(); + + if ( systemProperties != null ) + { + Enumeration<?> propertyKeys = systemProperties.propertyNames(); + + while ( propertyKeys.hasMoreElements() ) + { + String key = (String) propertyKeys.nextElement(); + + String value = systemProperties.getProperty( key ); + + if ( value == null ) + { + value = "null"; + } + + Xpp3Dom property = createElement( properties, "property" ); + + property.setAttribute( "name", key ); + + property.setAttribute( "value", value ); + + } + } + } +} http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/14f8995d/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/StatelessXmlReporter2.java ---------------------------------------------------------------------- diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/StatelessXmlReporter2.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/StatelessXmlReporter2.java new file mode 100644 index 0000000..05ebe2f --- /dev/null +++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/StatelessXmlReporter2.java @@ -0,0 +1,304 @@ +package org.apache.maven.plugin.surefire.report; + +/* + * 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. + */ + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.util.Enumeration; +import java.util.Properties; +import java.util.StringTokenizer; +import org.apache.maven.shared.utils.io.IOUtil; +import org.apache.maven.shared.utils.xml.XMLWriter; +import org.apache.maven.surefire.report.ReportEntry; +import org.apache.maven.surefire.report.ReporterException; +import org.apache.maven.surefire.report.SafeThrowable; + +/** + * XML format reporter writing to <code>TEST-<i>reportName</i>[-<i>suffix</i>].xml</code> file like written and read + * by Ant's <a href="http://ant.apache.org/manual/Tasks/junit.html"><code><junit></code></a> and + * <a href="http://ant.apache.org/manual/Tasks/junitreport.html"><code><junitreport></code></a> tasks, + * then supported by many tools like CI servers. + * <p/> + * <pre><?xml version="1.0" encoding="UTF-8"?> + * <testsuite name="<i>suite name</i>" [group="<i>group</i>"] tests="<i>0</i>" failures="<i>0</i>" errors="<i>0</i>" skipped="<i>0</i>" time="<i>0,###.###</i>"> + * <properties> + * <property name="<i>name</i>" value="<i>value</i>"/> + * [...] + * </properties> + * <testcase time="<i>0,###.###</i>" name="<i>test name</i> [classname="<i>class name</i>"] [group="<i>group</i>"]"/> + * <testcase time="<i>0,###.###</i>" name="<i>test name</i> [classname="<i>class name</i>"] [group="<i>group</i>"]"> + * <<b>error</b> message="<i>message</i>" type="<i>exception class name</i>"><i>stacktrace</i></error> + * <system-out><i>system out content (present only if not empty)</i></system-out> + * <system-err><i>system err content (present only if not empty)</i></system-err> + * </testcase> + * <testcase time="<i>0,###.###</i>" name="<i>test name</i> [classname="<i>class name</i>"] [group="<i>group</i>"]"> + * <<b>failure</b> message="<i>message</i>" type="<i>exception class name</i>"><i>stacktrace</i></failure> + * <system-out><i>system out content (present only if not empty)</i></system-out> + * <system-err><i>system err content (present only if not empty)</i></system-err> + * </testcase> + * <testcase time="<i>0,###.###</i>" name="<i>test name</i> [classname="<i>class name</i>"] [group="<i>group</i>"]"> + * <<b>skipped</b>/> + * </testcase> + * [...]</pre> + * + * @author <a href="mailto:jr...@exist.com">Johnny R. Ruiz III</a> + * @author Kristian Rosenvold + * @see <a href="http://wiki.apache.org/ant/Proposals/EnhancedTestReports">Ant's format enhancement proposal</a> + * (not yet implemented by Ant 1.8.2) + */ +public class StatelessXmlReporter2 +{ + private static final String LS = System.getProperty( "line.separator" ); + + private final File reportsDirectory; + + private final String reportNameSuffix; + + private final boolean trimStackTrace; + + public StatelessXmlReporter2( File reportsDirectory, String reportNameSuffix, boolean trimStackTrace ) + { + this.reportsDirectory = reportsDirectory; + this.reportNameSuffix = reportNameSuffix; + this.trimStackTrace = trimStackTrace; + } + + public void testSetCompleted( WrappedReportEntry testSetReportEntry, TestSetStats testSetStats ) + throws ReporterException + { + + FileWriter fw = getFileOutputStream( testSetReportEntry ); + + org.apache.maven.shared.utils.xml.XMLWriter ppw = + new org.apache.maven.shared.utils.xml.PrettyPrintXMLWriter( fw ); + ppw.setEncoding( "UTF-8" ); + + createTestSuiteElement( ppw, testSetReportEntry, testSetStats, reportNameSuffix ); + + showProperties( ppw ); + + + for ( WrappedReportEntry entry : testSetStats.getReportEntries() ) + { + if ( ReportEntryType.success.equals( entry.getReportEntryType() ) ) + { + startTestElement( ppw, entry, reportNameSuffix ); + ppw.endElement(); + } + else + { + getTestProblems( ppw, entry, trimStackTrace, reportNameSuffix ); + } + + } + + ppw.endElement(); // TestSuite + + + + try + { + + } + finally + { + IOUtil.close( fw ); + } + } + + private FileWriter getFileOutputStream( WrappedReportEntry testSetReportEntry ) + { + File reportFile = getReportFile( testSetReportEntry, reportsDirectory, reportNameSuffix ); + + File reportDir = reportFile.getParentFile(); + + //noinspection ResultOfMethodCallIgnored + reportDir.mkdirs(); + + try + { + return new FileWriter( reportFile ); + } + catch ( IOException e ) + { + throw new ReporterException( "When writing report", e ); + } + } + + private File getReportFile( ReportEntry report, File reportsDirectory, String reportNameSuffix ) + { + File reportFile; + + if ( reportNameSuffix != null && reportNameSuffix.length() > 0 ) + { + reportFile = new File( reportsDirectory, "TEST-" + report.getName() + "-" + reportNameSuffix + ".xml" ); + } + else + { + reportFile = new File( reportsDirectory, "TEST-" + report.getName() + ".xml" ); + } + + return reportFile; + } + + private static void startTestElement( XMLWriter ppw, WrappedReportEntry report, String reportNameSuffix ) + { + ppw.startElement( "testcase" ); + ppw.addAttribute( "name", report.getReportName() ); + if ( report.getGroup() != null ) + { + ppw.addAttribute( "group", report.getGroup() ); + } + if ( report.getSourceName() != null ) + { + if ( reportNameSuffix != null && reportNameSuffix.length() > 0 ) + { + ppw.addAttribute( "classname", report.getSourceName() + "(" + reportNameSuffix + ")" ); + } + else + { + ppw.addAttribute( "classname", report.getSourceName() ); + } + } + ppw.addAttribute( "time", report.elapsedTimeAsString() ); + } + + private static void createTestSuiteElement( XMLWriter ppw, WrappedReportEntry report, TestSetStats testSetStats, + String reportNameSuffix1 ) + { + ppw.startElement( "testsuite" ); + + ppw.addAttribute( "name", report.getReportName( reportNameSuffix1 ) ); + + if ( report.getGroup() != null ) + { + ppw.addAttribute( "group", report.getGroup() ); + } + + ppw.addAttribute( "time", testSetStats.getElapsedForTestSet() ); + + ppw.addAttribute( "tests", String.valueOf( testSetStats.getCompletedCount() ) ); + + ppw.addAttribute( "errors", String.valueOf( testSetStats.getErrors() ) ); + + ppw.addAttribute( "skipped", String.valueOf( testSetStats.getSkipped() ) ); + + ppw.addAttribute( "failures", String.valueOf( testSetStats.getFailures() ) ); + + } + + + private void getTestProblems( XMLWriter ppw, WrappedReportEntry report, boolean trimStackTrace, String reportNameSuffix ) + { + + startTestElement( ppw, report, reportNameSuffix ); + + ppw.startElement( report.getReportEntryType().name() ); + + String stackTrace = report.getStackTrace( trimStackTrace ); + + if ( report.getMessage() != null && report.getMessage().length() > 0 ) + { + ppw.addAttribute( "message", report.getMessage() ); + } + + if ( report.getStackTraceWriter() != null ) + { + //noinspection ThrowableResultOfMethodCallIgnored + SafeThrowable t = report.getStackTraceWriter().getThrowable(); + if ( t != null ) + { + if ( t.getMessage() != null ) + { + ppw.addAttribute( "type", ( stackTrace.contains( ":" ) + ? stackTrace.substring( 0, stackTrace.indexOf( ":" ) ) + : stackTrace ) ); + } + else + { + ppw.addAttribute( "type", new StringTokenizer( stackTrace ).nextToken() ); + } + } + } + + if ( stackTrace != null ) + { + ppw.writeText( stackTrace ); + } + + addOutputStreamElement( ppw, report.getStdout(), "system-out" ); + + addOutputStreamElement( ppw, report.getStdErr(), "system-err" ); + + ppw.endElement(); // entry type + ppw.endElement(); // test element + } + + private void addOutputStreamElement( XMLWriter xmlWriter, String stdOut, String name ) + { + if ( stdOut != null && stdOut.trim().length() > 0 ) + { + xmlWriter.startElement( name ); + xmlWriter.writeText( stdOut ); + xmlWriter.endElement(); + } + } + + /** + * Adds system properties to the XML report. + * <p/> + * + * @param xmlWriter The test suite to report to + */ + private void showProperties( XMLWriter xmlWriter ) + { + xmlWriter.startElement( "properties" ); + + Properties systemProperties = System.getProperties(); + + if ( systemProperties != null ) + { + Enumeration<?> propertyKeys = systemProperties.propertyNames(); + + while ( propertyKeys.hasMoreElements() ) + { + String key = (String) propertyKeys.nextElement(); + + String value = systemProperties.getProperty( key ); + + if ( value == null ) + { + value = "null"; + } + + xmlWriter.startElement( "property" ); + + xmlWriter.addAttribute( "name", key ); + + xmlWriter.addAttribute( "value", value ); + + xmlWriter.endElement(); + + } + } + xmlWriter.endElement(); + } +} http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/14f8995d/maven-surefire-common/src/main/java/org/apache/maven/surefire/report/RunStatistics.java ---------------------------------------------------------------------- diff --git a/maven-surefire-common/src/main/java/org/apache/maven/surefire/report/RunStatistics.java b/maven-surefire-common/src/main/java/org/apache/maven/surefire/report/RunStatistics.java index edbd5d5..139c3d7 100644 --- a/maven-surefire-common/src/main/java/org/apache/maven/surefire/report/RunStatistics.java +++ b/maven-surefire-common/src/main/java/org/apache/maven/surefire/report/RunStatistics.java @@ -1,145 +1,145 @@ -package org.apache.maven.surefire.report; - -/* - * 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. - */ - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import org.apache.maven.plugin.surefire.report.TestSetStats; -import org.apache.maven.surefire.suite.RunResult; - -/** - * @author Kristian Rosenvold - */ -public class RunStatistics -{ - /** - * Holds the source(s) that causes the error(s). - */ - private final Sources errorSources = new Sources(); - - /** - * Holds the source(s) that causes the failure(s). - */ - private final Sources failureSources = new Sources(); - - private int completedCount; - - private int errors; - - private int failures; - - private int skipped; - - - public void addErrorSource( StackTraceWriter stackTraceWriter ) - { - if ( stackTraceWriter == null ) - { - throw new IllegalArgumentException( "Cant be null" ); - } - errorSources.addSource( stackTraceWriter ); - } - - public void addFailureSource( StackTraceWriter stackTraceWriter ) - { - if ( stackTraceWriter == null ) - { - throw new IllegalArgumentException( "Cant be null" ); - } - failureSources.addSource( stackTraceWriter ); - } - - public Collection<String> getErrorSources() - { - return errorSources.getListOfSources(); - } - - public Collection<String> getFailureSources() - { - return failureSources.getListOfSources(); - } - - public synchronized boolean hadFailures() - { - return failures > 0; - } - - public synchronized boolean hadErrors() - { - return errors > 0; - } - - public synchronized int getCompletedCount() - { - return completedCount; - } - - public synchronized int getSkipped() - { - return skipped; - } - - public synchronized void add( TestSetStats testSetStats ) - { - this.completedCount += testSetStats.getCompletedCount(); - this.errors += testSetStats.getErrors(); - this.failures += testSetStats.getFailures(); - this.skipped += testSetStats.getSkipped(); - } - - public synchronized RunResult getRunResult() - { - return new RunResult( completedCount, errors, failures, skipped ); - } - - public synchronized String getSummary() - { - return "Tests run: " + completedCount + ", Failures: " + failures + ", Errors: " + errors + ", Skipped: " - + skipped; - } - - - private static class Sources - { - private final Collection<String> listOfSources = new ArrayList<String>(); - - void addSource( String source ) - { - synchronized ( listOfSources ) - { - listOfSources.add( source ); - } - } - - void addSource( StackTraceWriter stackTraceWriter ) - { - addSource( stackTraceWriter.smartTrimmedStackTrace() ); - } - - Collection<String> getListOfSources() - { - synchronized ( listOfSources ) - { - return Collections.unmodifiableCollection( listOfSources ); - } - } - } -} +package org.apache.maven.surefire.report; + +/* + * 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. + */ + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import org.apache.maven.plugin.surefire.report.TestSetStats; +import org.apache.maven.surefire.suite.RunResult; + +/** + * @author Kristian Rosenvold + */ +public class RunStatistics +{ + /** + * Holds the source(s) that causes the error(s). + */ + private final Sources errorSources = new Sources(); + + /** + * Holds the source(s) that causes the failure(s). + */ + private final Sources failureSources = new Sources(); + + private int completedCount; + + private int errors; + + private int failures; + + private int skipped; + + + public void addErrorSource( StackTraceWriter stackTraceWriter ) + { + if ( stackTraceWriter == null ) + { + throw new IllegalArgumentException( "Cant be null" ); + } + errorSources.addSource( stackTraceWriter ); + } + + public void addFailureSource( StackTraceWriter stackTraceWriter ) + { + if ( stackTraceWriter == null ) + { + throw new IllegalArgumentException( "Cant be null" ); + } + failureSources.addSource( stackTraceWriter ); + } + + public Collection<String> getErrorSources() + { + return errorSources.getListOfSources(); + } + + public Collection<String> getFailureSources() + { + return failureSources.getListOfSources(); + } + + public synchronized boolean hadFailures() + { + return failures > 0; + } + + public synchronized boolean hadErrors() + { + return errors > 0; + } + + public synchronized int getCompletedCount() + { + return completedCount; + } + + public synchronized int getSkipped() + { + return skipped; + } + + public synchronized void add( TestSetStats testSetStats ) + { + this.completedCount += testSetStats.getCompletedCount(); + this.errors += testSetStats.getErrors(); + this.failures += testSetStats.getFailures(); + this.skipped += testSetStats.getSkipped(); + } + + public synchronized RunResult getRunResult() + { + return new RunResult( completedCount, errors, failures, skipped ); + } + + public synchronized String getSummary() + { + return "Tests run: " + completedCount + ", Failures: " + failures + ", Errors: " + errors + ", Skipped: " + + skipped; + } + + + private static class Sources + { + private final Collection<String> listOfSources = new ArrayList<String>(); + + void addSource( String source ) + { + synchronized ( listOfSources ) + { + listOfSources.add( source ); + } + } + + void addSource( StackTraceWriter stackTraceWriter ) + { + addSource( stackTraceWriter.smartTrimmedStackTrace() ); + } + + Collection<String> getListOfSources() + { + synchronized ( listOfSources ) + { + return Collections.unmodifiableCollection( listOfSources ); + } + } + } +} http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/14f8995d/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/report/StatelessXMLReporterTest.java ---------------------------------------------------------------------- diff --git a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/report/StatelessXMLReporterTest.java b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/report/StatelessXMLReporterTest.java index a1e7b26..3bf5da8 100644 --- a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/report/StatelessXMLReporterTest.java +++ b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/report/StatelessXMLReporterTest.java @@ -20,9 +20,16 @@ package org.apache.maven.plugin.surefire.report; */ import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import org.apache.maven.plugin.surefire.booterclient.output.DeserializedStacktraceWriter; +import org.apache.maven.shared.utils.StringUtils; +import org.apache.maven.shared.utils.xml.Xpp3Dom; +import org.apache.maven.shared.utils.xml.Xpp3DomBuilder; import org.apache.maven.surefire.report.LegacyPojoStackTraceWriter; import org.apache.maven.surefire.report.ReportEntry; import org.apache.maven.surefire.report.SimpleReportEntry; +import org.apache.maven.surefire.report.StackTraceWriter; import junit.framework.AssertionFailedError; import junit.framework.TestCase; @@ -66,4 +73,59 @@ public class StatelessXMLReporterTest expectedReportFile.delete(); } -} + + public void testAllFieldsSerialized() + throws IOException + { + File reportDir = new File( "." ); + String testName = "aTestMethod"; + String testName2 = "bTestMethod"; + reportEntry = new SimpleReportEntry( this.getClass().getName(), testName, 12 ); + WrappedReportEntry testSetReportEntry = + new WrappedReportEntry( reportEntry, ReportEntryType.success, 12, null, null ); + File expectedReportFile = new File( reportDir, "TEST-" + testName + ".xml" ); + + stats.testSucceeded( testSetReportEntry ); + StackTraceWriter stackTraceWriter = new DeserializedStacktraceWriter( "A fud msg", "trimmed", "fail at foo" ); + WrappedReportEntry t2 = + new WrappedReportEntry( new SimpleReportEntry( Inner.class.getName(), testName2, stackTraceWriter, 13 ), + ReportEntryType.error, 13, "std-out!", "std-err?" ); + + stats.testSucceeded( t2 ); + StatelessXmlReporter reporter = new StatelessXmlReporter( new File( "." ), null, false ); + reporter.testSetCompleted( testSetReportEntry, stats ); + + Xpp3Dom testSuite = Xpp3DomBuilder.build( new FileReader( expectedReportFile ) ); + assertEquals( "testsuite", testSuite.getName() ); + Xpp3Dom properties = testSuite.getChild( "properties" ); + assertEquals( System.getProperties().size(), properties.getChildCount() ); + Xpp3Dom child = properties.getChild( 1 ); + assertFalse( StringUtils.isEmpty( child.getAttribute( "value" ) ) ); + assertFalse( StringUtils.isEmpty( child.getAttribute( "name" ) ) ); + + Xpp3Dom[] testcase = testSuite.getChildren( "testcase" ); + Xpp3Dom tca = testcase[0]; + assertEquals( testName, tca.getAttribute( "name" ) ); // Hopefully same order on jdk5 + assertEquals( "0.012", tca.getAttribute( "time" ) ); + assertEquals( this.getClass().getName(), tca.getAttribute( "classname" ) ); + + Xpp3Dom tcb = testcase[1]; + assertEquals( testName2, tcb.getAttribute( "name" ) ); + assertEquals( "0.013", tcb.getAttribute( "time" ) ); + assertEquals( Inner.class.getName(), tcb.getAttribute( "classname" ) ); + Xpp3Dom errorNode = tcb.getChild( "error" ); + assertNotNull( errorNode ); + assertEquals( "A fud msg", errorNode.getAttribute( "message" ) ); + assertEquals( "fail at foo", errorNode.getAttribute( "type" ) ); + assertEquals( "std-out!", tcb.getChild( "system-out" ).getValue() ); + assertEquals( "std-err?", tcb.getChild( "system-err" ).getValue() ); + + expectedReportFile.delete(); + } + + class Inner + { + + } + +} \ No newline at end of file