diff --git a/junit-report/src/main/org/apache/maven/plugins/junitreport/ExceptionTool.java b/junit-report/src/main/org/apache/maven/plugins/junitreport/ExceptionTool.java new file mode 100644 index 00000000..fd4ff482 --- /dev/null +++ b/junit-report/src/main/org/apache/maven/plugins/junitreport/ExceptionTool.java @@ -0,0 +1,176 @@ +package org.apache.maven.plugins.junitreport; + +/* ==================================================================== + * Copyright 2006 The Apache Software Foundation. + * + * 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. + * ==================================================================== + */ + +/* + * Created on Jun 5, 2005 + */ + +import java.util.ArrayList; +import java.util.List; + +/** + *
+ * Util class for exceptions + *
+ *+ * Inspired from {@link org.apache.maven.util.StringTool} + *
+ * + * @author Cyrille Le Clerc + * @version $Id$ + */ +public class ExceptionTool +{ + /** + *+ * Splits the provided text into an array, separator String specified. + *
+ *+ * This method is different of {@link java.util.StringTokenizer} that only + * accept chars as separator but not strings + *
+ * + * @param text + * the string to split + * @param separator + * the spearator + * @return An array containing the split string + */ + public String[] split( String text, String separator ) + { + if ( text == null ) + { + return null; + } + + List result = new ArrayList(); + int fromIndex = 0; + int idx; + + while ( ( idx = text.indexOf( separator, fromIndex ) ) != -1 ) + { + String subString = text.substring( fromIndex, idx ); + + result.add( subString ); + fromIndex = idx + separator.length(); + } + + if ( fromIndex != text.length() ) + { + // add last element + String subString = text.substring( fromIndex ); + + result.add( subString ); + } + + return (String[]) result.toArray( new String[result.size()] ); + } + + /** + *
+ * Splits the given stacktrace into an array of simple (not
+ * nested) stack traces. The nesting stack trace is included in the result
+ *
+ * Truncates the given stacktrace just before the first occurance of the
+ * given searchedString
+ *
+ * Splits the given stackTrace into nested stack traces and
+ * truncates each of the nested stacktrace (including the nesting
+ * stacktrace) then re-concatenates the string to return it
+ *
+ Contains utility classes for the junit-report plugin. +
+ + diff --git a/junit-report/src/plugin-resources/junit.jsl b/junit-report/src/plugin-resources/junit.jsl index 3cc04d1c..bc28e786 100644 --- a/junit-report/src/plugin-resources/junit.jsl +++ b/junit-report/src/plugin-resources/junit.jsl @@ -30,7 +30,7 @@ xmlns:ant="jelly:ant" trim="false"> -
-${stringTool.splitStringAtLastDelim(stringTool.splitStringAtLastDelim(failure.text, 'at org.apache.commons.jelly.tags.ant.AntTag.doTag').get(0),
-'at sun.reflect.NativeMethodAccessorImpl.invoke0(').get(0)}
+${exceptionTool.truncateNestedStackTrace(exceptionTool.truncateNestedStackTrace(failure.text, 'at org.apache.commons.jelly.tags.ant.AntTag.doTag'),
+'at sun.reflect.NativeMethodAccessorImpl.invoke0(')}
diff --git a/junit-report/src/test/org/apache/maven/plugins/junitreport/ExceptionToolTest.java b/junit-report/src/test/org/apache/maven/plugins/junitreport/ExceptionToolTest.java
new file mode 100644
index 00000000..c56d742d
--- /dev/null
+++ b/junit-report/src/test/org/apache/maven/plugins/junitreport/ExceptionToolTest.java
@@ -0,0 +1,290 @@
+package org.apache.maven.plugins.junitreport;
+
+/* ====================================================================
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * 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.
+ * ====================================================================
+ */
+
+/*
+ * Created on Jun 5, 2005
+ */
+
+import junit.framework.TestCase;
+
+/**
+ * @author Cyrille Le Clerc
+ * @version $Id$
+ */
+public class ExceptionToolTest extends TestCase
+{
+ private String[] m_nestedStackTraces =
+ new String[]
+ {
+ "java.lang.Exception: The nested Exception\r\n"
+ + " at com.mycompany.test.MyTest.testNestedException(MyTest.java:16)\r\n"
+ + " at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\r\n"
+ + " at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)\r\n"
+ + " at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)\r\n"
+ + " at org.apache.commons.jelly.tags.ant.AntTag.doTag(AntTag.java:195)\r\n"
+ + " at org.apache.commons.jelly.impl.TagScript.run(TagScript.java:279)\r\n"
+ + " at org.apache.commons.jelly.impl.ScriptBlock.run(ScriptBlock.java:135)\r\n"
+ + " at org.apache.commons.jelly.TagSupport.invokeBody(TagSupport.java:233)\r\n"
+ + " at org.apache.commons.jelly.tags.core.IfTag.doTag(IfTag.java:88)\r\n"
+ + " at org.apache.commons.jelly.impl.TagScript.run(TagScript.java:279)\r\n"
+ + " at org.apache.commons.jelly.impl.ScriptBlock.run(ScriptBlock.java:135)\r\n"
+ + " at org.apache.maven.jelly.tags.werkz.MavenGoalTag.runBodyTag(MavenGoalTag.java:79)\r\n"
+ + " at org.apache.maven.jelly.tags.werkz.MavenGoalTag$MavenGoalAction.performAction(MavenGoalTag.java:110)\r\n"
+ + " at com.werken.werkz.Goal.fire(Goal.java:639)\r\n"
+ + " at com.werken.werkz.Goal.attain(Goal.java:575)\r\n"
+ + " at com.werken.werkz.WerkzProject.attainGoal(WerkzProject.java:193)\r\n"
+ + " at org.apache.maven.jelly.tags.werkz.MavenAttainGoalTag.doTag(MavenAttainGoalTag.java:127)\r\n"
+ + " at org.apache.commons.jelly.impl.TagScript.run(TagScript.java:279)\r\n"
+ + " at org.apache.commons.jelly.impl.ScriptBlock.run(ScriptBlock.java:135)\r\n"
+ + " at org.apache.commons.jelly.TagSupport.invokeBody(TagSupport.java:233)\r\n"
+ + " at org.apache.commons.jelly.tags.core.IfTag.doTag(IfTag.java:88)\r\n"
+ + " at org.apache.commons.jelly.impl.TagScript.run(TagScript.java:279)\r\n"
+ + " at org.apache.commons.jelly.impl.ScriptBlock.run(ScriptBlock.java:135)\r\n"
+ + " at org.apache.maven.jelly.tags.werkz.MavenGoalTag.runBodyTag(MavenGoalTag.java:79)\r\n"
+ + " at org.apache.maven.jelly.tags.werkz.MavenGoalTag$MavenGoalAction.performAction(MavenGoalTag.java:110)\r\n"
+ + " at com.werken.werkz.Goal.fire(Goal.java:639)\r\n"
+ + " at com.werken.werkz.Goal.attain(Goal.java:575)\r\n"
+ + " at com.werken.werkz.Goal.attainPrecursors(Goal.java:488)\r\n"
+ + " at com.werken.werkz.Goal.attain(Goal.java:573)\r\n"
+ + " at com.werken.werkz.WerkzProject.attainGoal(WerkzProject.java:193)\r\n"
+ + " at org.apache.maven.jelly.tags.werkz.MavenAttainGoalTag.doTag(MavenAttainGoalTag.java:127)\r\n"
+ + " at org.apache.commons.jelly.impl.TagScript.run(TagScript.java:279)\r\n"
+ + " at org.apache.commons.jelly.impl.ScriptBlock.run(ScriptBlock.java:135)\r\n"
+ + " at org.apache.commons.jelly.TagSupport.invokeBody(TagSupport.java:233)\r\n"
+ + " at org.apache.commons.jelly.tags.core.IfTag.doTag(IfTag.java:88)\r\n"
+ + " at org.apache.commons.jelly.impl.TagScript.run(TagScript.java:279)\r\n"
+ + " at org.apache.commons.jelly.impl.ScriptBlock.run(ScriptBlock.java:135)\r\n"
+ + " at org.apache.commons.jelly.TagSupport.invokeBody(TagSupport.java:233)\r\n"
+ + " at org.apache.commons.jelly.tags.core.ForEachTag.doTag(ForEachTag.java:145)\r\n"
+ + " at org.apache.commons.jelly.impl.TagScript.run(TagScript.java:279)\r\n"
+ + " at org.apache.commons.jelly.impl.ScriptBlock.run(ScriptBlock.java:135)\r\n"
+ + " at org.apache.maven.jelly.tags.werkz.MavenGoalTag.runBodyTag(MavenGoalTag.java:79)\r\n"
+ + " at org.apache.maven.jelly.tags.werkz.MavenGoalTag$MavenGoalAction.performAction(MavenGoalTag.java:110)\r\n"
+ + " at com.werken.werkz.Goal.fire(Goal.java:639)\r\n"
+ + " at com.werken.werkz.Goal.attain(Goal.java:575)\r\n"
+ + " at com.werken.werkz.WerkzProject.attainGoal(WerkzProject.java:193)\r\n"
+ + " at org.apache.maven.jelly.tags.werkz.MavenAttainGoalTag.doTag(MavenAttainGoalTag.java:127)\r\n"
+ + " at org.apache.commons.jelly.impl.TagScript.run(TagScript.java:279)\r\n"
+ + " at org.apache.commons.jelly.impl.ScriptBlock.run(ScriptBlock.java:135)\r\n"
+ + " at org.apache.maven.jelly.tags.werkz.MavenGoalTag.runBodyTag(MavenGoalTag.java:79)\r\n"
+ + " at org.apache.maven.jelly.tags.werkz.MavenGoalTag$MavenGoalAction.performAction(MavenGoalTag.java:110)\r\n"
+ + " at com.werken.werkz.Goal.fire(Goal.java:639)\r\n"
+ + " at com.werken.werkz.Goal.attain(Goal.java:575)\r\n"
+ + " at org.apache.maven.plugin.PluginManager.attainGoals(PluginManager.java:671)\r\n"
+ + " at org.apache.maven.MavenSession.attainGoals(MavenSession.java:263)\r\n"
+ + " at org.apache.maven.cli.App.doMain(App.java:488)\r\n"
+ + " at org.apache.maven.cli.App.main(App.java:1239)\r\n"
+ + " at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\r\n"
+ + " at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)\r\n"
+ + " at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)\r\n"
+ + " at com.werken.forehead.Forehead.run(Forehead.java:551)\r\n"
+ + " at com.werken.forehead.Forehead.main(Forehead.java:581)\r\n",
+ "Caused by: java.lang.Exception: The cause Exception\r\n"
+ + " at com.mycompany.test.MyTest.testNestedException(MyTest.java:15)\r\n"
+ + " ... 76 more\r\n"
+ };
+ private String m_nestedStackTrace =
+ m_nestedStackTraces[0] + m_nestedStackTraces[1];
+ private String[] m_truncatedNestedStackTraces =
+ new String[]
+ {
+ "java.lang.Exception: The nested Exception\r\n"
+ + " at com.mycompany.test.MyTest.testNestedException(MyTest.java:16)\r\n"
+ + " at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\r\n"
+ + " at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)\r\n"
+ + " at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)\r\n",
+ "Caused by: java.lang.Exception: The cause Exception\r\n"
+ + " at com.mycompany.test.MyTest.testNestedException(MyTest.java:15)\r\n"
+ + " ... 76 more\r\n"
+ };
+ private String m_truncatedNestedStackTrace =
+ m_truncatedNestedStackTraces[0] + " ... more\r\n"
+ + m_truncatedNestedStackTraces[1] + "\r\n";
+ private String m_stackTrace =
+ "java.lang.Exception: The Exception\r\n"
+ + " at com.mycompany.test.MyTest.testNestedException(MyTest.java:16)\r\n"
+ + " at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\r\n"
+ + " at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)\r\n"
+ + " at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)\r\n"
+ + " at org.apache.commons.jelly.tags.ant.AntTag.doTag(AntTag.java:195)\r\n"
+ + " at org.apache.commons.jelly.impl.TagScript.run(TagScript.java:279)\r\n"
+ + " at org.apache.commons.jelly.impl.ScriptBlock.run(ScriptBlock.java:135)\r\n"
+ + " at org.apache.commons.jelly.TagSupport.invokeBody(TagSupport.java:233)\r\n"
+ + " at org.apache.commons.jelly.tags.core.IfTag.doTag(IfTag.java:88)\r\n"
+ + " at org.apache.commons.jelly.impl.TagScript.run(TagScript.java:279)\r\n"
+ + " at org.apache.commons.jelly.impl.ScriptBlock.run(ScriptBlock.java:135)\r\n"
+ + " at org.apache.maven.jelly.tags.werkz.MavenGoalTag.runBodyTag(MavenGoalTag.java:79)\r\n"
+ + " at org.apache.maven.jelly.tags.werkz.MavenGoalTag$MavenGoalAction.performAction(MavenGoalTag.java:110)\r\n"
+ + " at com.werken.werkz.Goal.fire(Goal.java:639)\r\n"
+ + " at com.werken.werkz.Goal.attain(Goal.java:575)\r\n"
+ + " at com.werken.werkz.WerkzProject.attainGoal(WerkzProject.java:193)\r\n"
+ + " at org.apache.maven.jelly.tags.werkz.MavenAttainGoalTag.doTag(MavenAttainGoalTag.java:127)\r\n"
+ + " at org.apache.commons.jelly.impl.TagScript.run(TagScript.java:279)\r\n"
+ + " at org.apache.commons.jelly.impl.ScriptBlock.run(ScriptBlock.java:135)\r\n"
+ + " at org.apache.commons.jelly.TagSupport.invokeBody(TagSupport.java:233)\r\n"
+ + " at org.apache.commons.jelly.tags.core.IfTag.doTag(IfTag.java:88)\r\n"
+ + " at org.apache.commons.jelly.impl.TagScript.run(TagScript.java:279)\r\n"
+ + " at org.apache.commons.jelly.impl.ScriptBlock.run(ScriptBlock.java:135)\r\n"
+ + " at org.apache.maven.jelly.tags.werkz.MavenGoalTag.runBodyTag(MavenGoalTag.java:79)\r\n"
+ + " at org.apache.maven.jelly.tags.werkz.MavenGoalTag$MavenGoalAction.performAction(MavenGoalTag.java:110)\r\n"
+ + " at com.werken.werkz.Goal.fire(Goal.java:639)\r\n"
+ + " at com.werken.werkz.Goal.attain(Goal.java:575)\r\n"
+ + " at com.werken.werkz.Goal.attainPrecursors(Goal.java:488)\r\n"
+ + " at com.werken.werkz.Goal.attain(Goal.java:573)\r\n"
+ + " at com.werken.werkz.WerkzProject.attainGoal(WerkzProject.java:193)\r\n"
+ + " at org.apache.maven.jelly.tags.werkz.MavenAttainGoalTag.doTag(MavenAttainGoalTag.java:127)\r\n"
+ + " at org.apache.commons.jelly.impl.TagScript.run(TagScript.java:279)\r\n"
+ + " at org.apache.commons.jelly.impl.ScriptBlock.run(ScriptBlock.java:135)\r\n"
+ + " at org.apache.commons.jelly.TagSupport.invokeBody(TagSupport.java:233)\r\n"
+ + " at org.apache.commons.jelly.tags.core.IfTag.doTag(IfTag.java:88)\r\n"
+ + " at org.apache.commons.jelly.impl.TagScript.run(TagScript.java:279)\r\n"
+ + " at org.apache.commons.jelly.impl.ScriptBlock.run(ScriptBlock.java:135)\r\n"
+ + " at org.apache.commons.jelly.TagSupport.invokeBody(TagSupport.java:233)\r\n"
+ + " at org.apache.commons.jelly.tags.core.ForEachTag.doTag(ForEachTag.java:145)\r\n"
+ + " at org.apache.commons.jelly.impl.TagScript.run(TagScript.java:279)\r\n"
+ + " at org.apache.commons.jelly.impl.ScriptBlock.run(ScriptBlock.java:135)\r\n"
+ + " at org.apache.maven.jelly.tags.werkz.MavenGoalTag.runBodyTag(MavenGoalTag.java:79)\r\n"
+ + " at org.apache.maven.jelly.tags.werkz.MavenGoalTag$MavenGoalAction.performAction(MavenGoalTag.java:110)\r\n"
+ + " at com.werken.werkz.Goal.fire(Goal.java:639)\r\n"
+ + " at com.werken.werkz.Goal.attain(Goal.java:575)\r\n"
+ + " at com.werken.werkz.WerkzProject.attainGoal(WerkzProject.java:193)\r\n"
+ + " at org.apache.maven.jelly.tags.werkz.MavenAttainGoalTag.doTag(MavenAttainGoalTag.java:127)\r\n"
+ + " at org.apache.commons.jelly.impl.TagScript.run(TagScript.java:279)\r\n"
+ + " at org.apache.commons.jelly.impl.ScriptBlock.run(ScriptBlock.java:135)\r\n"
+ + " at org.apache.maven.jelly.tags.werkz.MavenGoalTag.runBodyTag(MavenGoalTag.java:79)\r\n"
+ + " at org.apache.maven.jelly.tags.werkz.MavenGoalTag$MavenGoalAction.performAction(MavenGoalTag.java:110)\r\n"
+ + " at com.werken.werkz.Goal.fire(Goal.java:639)\r\n"
+ + " at com.werken.werkz.Goal.attain(Goal.java:575)\r\n"
+ + " at org.apache.maven.plugin.PluginManager.attainGoals(PluginManager.java:671)\r\n"
+ + " at org.apache.maven.MavenSession.attainGoals(MavenSession.java:263)\r\n"
+ + " at org.apache.maven.cli.App.doMain(App.java:488)\r\n"
+ + " at org.apache.maven.cli.App.main(App.java:1239)\r\n"
+ + " at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\r\n"
+ + " at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)\r\n"
+ + " at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)\r\n"
+ + " at com.werken.forehead.Forehead.run(Forehead.java:551)\r\n"
+ + " at com.werken.forehead.Forehead.main(Forehead.java:581)\r\n";
+ private String m_truncatedStackTrace =
+ "java.lang.Exception: The Exception\r\n"
+ + " at com.mycompany.test.MyTest.testNestedException(MyTest.java:16)\r\n"
+ + " at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\r\n"
+ + " at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)\r\n"
+ + " at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)\r\n"
+ + " ... more";
+
+ public static void main( String[] args )
+ {
+ junit.textui.TestRunner.run( ExceptionToolTest.class );
+ }
+
+ public void testSplitNestedStackTraces()
+ {
+ ExceptionTool exceptionTool = new ExceptionTool();
+ String[] stackTraces =
+ exceptionTool.splitNestedStackTraces( m_nestedStackTrace );
+
+ for ( int i = 0; i < stackTraces.length; i++ )
+ {
+ String actual = stackTraces[i];
+ String expected = m_nestedStackTraces[i];
+
+ assertEquals( "nestedStack " + i, expected, actual );
+ }
+ }
+
+ public void testTruncateStackTrace()
+ {
+ String searchedString =
+ "at org.apache.commons.jelly.tags.ant.AntTag.doTag";
+ ExceptionTool exceptionTool = new ExceptionTool();
+ String expected = m_truncatedStackTrace;
+ String actual =
+ exceptionTool.truncateStackTrace( m_stackTrace, searchedString );
+
+ assertEquals( expected, actual );
+ }
+
+ public void testTruncateNestedStackTrace()
+ {
+ String searchedString =
+ "at org.apache.commons.jelly.tags.ant.AntTag.doTag";
+ ExceptionTool exceptionTool = new ExceptionTool();
+ String expected = m_truncatedNestedStackTrace;
+ String actual =
+ exceptionTool.truncateNestedStackTrace( m_nestedStackTrace,
+ searchedString );
+
+ assertEquals( expected, actual );
+ }
+
+ public void testSplit()
+ {
+ String str =
+ "value 1 separator value 2 separator value 3 separator value 4 separator value 5";
+ String[] expected =
+ new String[]
+ {
+ "value 1 ", " value 2 ", " value 3 ", " value 4 ", " value 5"
+ };
+ ExceptionTool exceptionTool = new ExceptionTool();
+ String[] actual = exceptionTool.split( str, "separator" );
+
+ assertEquals( "result size", expected.length, actual.length );
+
+ for ( int i = 0; i < actual.length; i++ )
+ {
+ assertEquals( "value " + i, expected[i], actual[i] );
+ }
+ }
+
+ public void testSplitWithNoTrailingValue()
+ {
+ String str =
+ "value 1 separator value 2 separator value 3 separator value 4 separator value 5separator";
+ String[] expected =
+ new String[]
+ {
+ "value 1 ", " value 2 ", " value 3 ", " value 4 ", " value 5"
+ };
+ ExceptionTool exceptionTool = new ExceptionTool();
+ String[] actual = exceptionTool.split( str, "separator" );
+
+ assertEquals( "result size", expected.length, actual.length );
+
+ for ( int i = 0; i < actual.length; i++ )
+ {
+ assertEquals( "value " + i, expected[i], actual[i] );
+ }
+ }
+
+ public void testSplitWithNoSeparator()
+ {
+ String str = "value 1 ";
+ String[] expected = new String[] { "value 1 " };
+ ExceptionTool exceptionTool = new ExceptionTool();
+ String[] actual = exceptionTool.split( str, "separator" );
+
+ assertEquals( "result size", expected.length, actual.length );
+
+ for ( int i = 0; i < actual.length; i++ )
+ {
+ assertEquals( "value " + i, expected[i], actual[i] );
+ }
+ }
+}
diff --git a/junit-report/src/test/org/apache/maven/plugins/junitreport/package.html b/junit-report/src/test/org/apache/maven/plugins/junitreport/package.html
new file mode 100644
index 00000000..0e7e3c4c
--- /dev/null
+++ b/junit-report/src/test/org/apache/maven/plugins/junitreport/package.html
@@ -0,0 +1,11 @@
+
+
+
+ + Test classes for org.apache.maven.plugins.junitreport +
+ + diff --git a/junit-report/xdocs/changes.xml b/junit-report/xdocs/changes.xml index f9c10d6b..f0bea2f6 100644 --- a/junit-report/xdocs/changes.xml +++ b/junit-report/xdocs/changes.xml @@ -26,6 +26,7 @@