#616 closed defect (fixed)
JUnit xml parsing doesn't always work
Reported by: | anonymous | Owned by: | osimons |
---|---|---|---|
Priority: | major | Milestone: | 0.6.1 |
Component: | General | Version: | 0.6b2 |
Keywords: | Cc: | bkalbfus@… | |
Operating System: | Linux |
Description
When a junit xml file has a testsuites element at the top level, the bitten parser doesn't work. Here is a sample output from gtest:
<?xml version="1.0" encoding="UTF-8"?> <testsuites tests="13" failures="0" disabled="0" errors="0" time="0.002" name="AllTests"> <testsuite name="Vector" tests="13" failures="0" disabled="0" errors="0" time="0.001"> <testcase name="Static" status="run" time="0" classname="Vector" /> <testcase name="Dynamic" status="run" time="0" classname="Vector" /> <testcase name="Proxy" status="run" time="0" classname="Vector" /> <testcase name="SubVector" status="run" time="0" classname="Vector" /> <testcase name="IOStream" status="run" time="0" classname="Vector" /> <testcase name="Equality" status="run" time="0" classname="Vector" /> <testcase name="BasicMath" status="run" time="0" classname="Vector" /> <testcase name="ElemCompare" status="run" time="0" classname="Vector" /> <testcase name="Norms" status="run" time="0" classname="Vector" /> <testcase name="Funcs" status="run" time="0" classname="Vector" /> <testcase name="Transpose" status="run" time="0" classname="Vector" /> <testcase name="Real" status="run" time="0" classname="Vector" /> <testcase name="Imag" status="run" time="0" classname="Vector" /> </testsuite> </testsuites>
This quick fix makes bitten parse it, but would break instances where there was no testsuites element:
--- /usr/lib/python2.4/site-packages/bitten/build/javatools.py 2010-02-11 09:43:22.000000000 -0800 +++ javatools.py.new 2010-09-20 15:57:51.000000000 -0700 @@ -118,7 +118,8 @@ for path in glob(ctxt.resolve(file_)): fileobj = file(path, 'r') try: - for testcase in xmlio.parse(fileobj).children('testcase'): + for testsuite in xmlio.parse(fileobj).children('testsuite'): + for testcase in testsuite.children('testcase'): test = xmlio.Element('test') test.attr['fixture'] = testcase.attr['classname'] test.attr['name'] = testcase.attr['name']
Attachments (0)
Change History (4)
comment:1 Changed 12 years ago by hodgestar
- Owner set to hodgestar
- Status changed from new to assigned
comment:2 Changed 12 years ago by bkalbfus@…
- Cc bkalbfus@… added
There are two scenarios:
- root node is testsuite. This is handled by current code
- root node is testsuites. This is a pure wrapper for multiple instances of testsuite.
junit.xsd I got from http://windyroad.com.au/dl/Open%20Source/JUnit.xsd defines it precisely:
<?xml version="1.0" encoding="UTF-8"?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified"> <xs:annotation> <xs:documentation xml:lang="en">JUnit test result schema for the Apache Ant JUnit and JUnitReport tasks Copyright © 2011, Windy Road Technology Pty. Limited The Apache Ant JUnit XML Schema is distributed under the terms of the GNU Lesser General Public License (LGPL) http://www.gnu.org/licenses/lgpl.html Permission to waive conditions of this license may be requested from Windy Road Support (http://windyroad.org/support).</xs:documentation> </xs:annotation> <xs:element name="testsuite" type="testsuite"/> <xs:simpleType name="ISO8601_DATETIME_PATTERN"> <xs:restriction base="xs:dateTime"> <xs:pattern value="[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}"/> </xs:restriction> </xs:simpleType> <xs:element name="testsuites"> <xs:annotation> <xs:documentation xml:lang="en">Contains an aggregation of testsuite results</xs:documentation> </xs:annotation> <xs:complexType> <xs:sequence> <xs:element name="testsuite" minOccurs="0" maxOccurs="unbounded"> <xs:complexType> <xs:complexContent> <xs:extension base="testsuite"> <xs:attribute name="package" type="xs:token" use="required"> <xs:annotation> <xs:documentation xml:lang="en">Derived from testsuite/@name in the non-aggregated documents</xs:documentation> </xs:annotation> </xs:attribute> <xs:attribute name="id" type="xs:int" use="required"> <xs:annotation> <xs:documentation xml:lang="en">Starts at '0' for the first testsuite and is incremented by 1 for each following testsuite</xs:documentation> </xs:annotation> </xs:attribute> </xs:extension> </xs:complexContent> </xs:complexType> </xs:element> </xs:sequence> </xs:complexType> </xs:element> <xs:complexType name="testsuite"> <xs:annotation> <xs:documentation xml:lang="en">Contains the results of exexuting a testsuite</xs:documentation> </xs:annotation> <xs:sequence> <xs:element name="properties"> <xs:annotation> <xs:documentation xml:lang="en">Properties (e.g., environment settings) set during test execution</xs:documentation> </xs:annotation> <xs:complexType> <xs:sequence> <xs:element name="property" minOccurs="0" maxOccurs="unbounded"> <xs:complexType> <xs:attribute name="name" use="required"> <xs:simpleType> <xs:restriction base="xs:token"> <xs:minLength value="1"/> </xs:restriction> </xs:simpleType> </xs:attribute> <xs:attribute name="value" type="xs:string" use="required"/> </xs:complexType> </xs:element> </xs:sequence> </xs:complexType> </xs:element> <xs:element name="testcase" minOccurs="0" maxOccurs="unbounded"> <xs:complexType> <xs:choice minOccurs="0"> <xs:element name="error"> <xs:annotation> <xs:documentation xml:lang="en">Indicates that the test errored. An errored test is one that had an unanticipated problem. e.g., an unchecked throwable; or a problem with the implementation of the test. Contains as a text node relevant data for the error, e.g., a stack trace</xs:documentation> </xs:annotation> <xs:complexType> <xs:simpleContent> <xs:extension base="pre-string"> <xs:attribute name="message" type="xs:string"> <xs:annotation> <xs:documentation xml:lang="en">The error message. e.g., if a java exception is thrown, the return value of getMessage()</xs:documentation> </xs:annotation> </xs:attribute> <xs:attribute name="type" type="xs:string" use="required"> <xs:annotation> <xs:documentation xml:lang="en">The type of error that occured. e.g., if a java execption is thrown the full class name of the exception.</xs:documentation> </xs:annotation> </xs:attribute> </xs:extension> </xs:simpleContent> </xs:complexType> </xs:element> <xs:element name="failure"> <xs:annotation> <xs:documentation xml:lang="en">Indicates that the test failed. A failure is a test which the code has explicitly failed by using the mechanisms for that purpose. e.g., via an assertEquals. Contains as a text node relevant data for the failure, e.g., a stack trace</xs:documentation> </xs:annotation> <xs:complexType> <xs:simpleContent> <xs:extension base="pre-string"> <xs:attribute name="message" type="xs:string"> <xs:annotation> <xs:documentation xml:lang="en">The message specified in the assert</xs:documentation> </xs:annotation> </xs:attribute> <xs:attribute name="type" type="xs:string" use="required"> <xs:annotation> <xs:documentation xml:lang="en">The type of the assert.</xs:documentation> </xs:annotation> </xs:attribute> </xs:extension> </xs:simpleContent> </xs:complexType> </xs:element> </xs:choice> <xs:attribute name="name" type="xs:token" use="required"> <xs:annotation> <xs:documentation xml:lang="en">Name of the test method</xs:documentation> </xs:annotation> </xs:attribute> <xs:attribute name="classname" type="xs:token" use="required"> <xs:annotation> <xs:documentation xml:lang="en">Full class name for the class the test method is in.</xs:documentation> </xs:annotation> </xs:attribute> <xs:attribute name="time" type="xs:decimal" use="required"> <xs:annotation> <xs:documentation xml:lang="en">Time taken (in seconds) to execute the test</xs:documentation> </xs:annotation> </xs:attribute> </xs:complexType> </xs:element> <xs:element name="system-out"> <xs:annotation> <xs:documentation xml:lang="en">Data that was written to standard out while the test was executed</xs:documentation> </xs:annotation> <xs:simpleType> <xs:restriction base="pre-string"> <xs:whiteSpace value="preserve"/> </xs:restriction> </xs:simpleType> </xs:element> <xs:element name="system-err"> <xs:annotation> <xs:documentation xml:lang="en">Data that was written to standard error while the test was executed</xs:documentation> </xs:annotation> <xs:simpleType> <xs:restriction base="pre-string"> <xs:whiteSpace value="preserve"/> </xs:restriction> </xs:simpleType> </xs:element> </xs:sequence> <xs:attribute name="name" use="required"> <xs:annotation> <xs:documentation xml:lang="en">Full class name of the test for non-aggregated testsuite documents. Class name without the package for aggregated testsuites documents</xs:documentation> </xs:annotation> <xs:simpleType> <xs:restriction base="xs:token"> <xs:minLength value="1"/> </xs:restriction> </xs:simpleType> </xs:attribute> <xs:attribute name="timestamp" type="ISO8601_DATETIME_PATTERN" use="required"> <xs:annotation> <xs:documentation xml:lang="en">when the test was executed. Timezone may not be specified.</xs:documentation> </xs:annotation> </xs:attribute> <xs:attribute name="hostname" use="required"> <xs:annotation> <xs:documentation xml:lang="en">Host on which the tests were executed. 'localhost' should be used if the hostname cannot be determined.</xs:documentation> </xs:annotation> <xs:simpleType> <xs:restriction base="xs:token"> <xs:minLength value="1"/> </xs:restriction> </xs:simpleType> </xs:attribute> <xs:attribute name="tests" type="xs:int" use="required"> <xs:annotation> <xs:documentation xml:lang="en">The total number of tests in the suite</xs:documentation> </xs:annotation> </xs:attribute> <xs:attribute name="failures" type="xs:int" use="required"> <xs:annotation> <xs:documentation xml:lang="en">The total number of tests in the suite that failed. A failure is a test which the code has explicitly failed by using the mechanisms for that purpose. e.g., via an assertEquals</xs:documentation> </xs:annotation> </xs:attribute> <xs:attribute name="errors" type="xs:int" use="required"> <xs:annotation> <xs:documentation xml:lang="en">The total number of tests in the suite that errorrd. An errored test is one that had an unanticipated problem. e.g., an unchecked throwable; or a problem with the implementation of the test.</xs:documentation> </xs:annotation> </xs:attribute> <xs:attribute name="time" type="xs:decimal" use="required"> <xs:annotation> <xs:documentation xml:lang="en">Time taken (in seconds) to execute the tests in the suite</xs:documentation> </xs:annotation> </xs:attribute> </xs:complexType> <xs:simpleType name="pre-string"> <xs:restriction base="xs:string"> <xs:whiteSpace value="preserve"/> </xs:restriction> </xs:simpleType> </xs:schema>
Interesting that I don't see the attributes the ticket originator has on his testsuites xml. I was looking for such attributes but I made do without them because they weren't in the xsd.
comment:3 Changed 12 years ago by osimons
- Resolution set to fixed
- Status changed from assigned to closed
comment:4 Changed 12 years ago by osimons
- Owner changed from hodgestar to osimons
BTW, I missed the comments on this ticket while working on my patch. Happy to see that the schema confirms this additional wrapper.
Is it possible for a JUnit file to not have a testsuite element? If so, I think this code needs to handle both the case where one is present and where one is not. Happy to commit such a patch if it has a test case.