TestReport v0.1

The schema of pyTooling’s own test report format, which pyTooling.Testing.ReportWriter writes and every generated report points at with xsi:noNamespaceSchemaLocation="TestReport-v0.1.xsd".

It differs from JUnit XML in the two ways JUnit cannot express: test suites nest, instead of being flattened into a dotted classname, and every item carries four names - an identifier, a title, a summary and a description - instead of one name and a bag of <property> pairs.

Validate a report

xmllint --schema TestReport-v0.1.xsd --noout TestReport.xml

See also

A Report Format of One’s Own

→ What the format is for, and an example document.

The schema

→ Reaching the schema from Python and validating with xmlschema.

Diagram

Every complex type is a record of three compartments - its name, its attributes, and its simple-typed child elements with their cardinality. A complex-typed child element is an edge, so containment is visible as structure rather than as a repeated type name, and testsuite’s edge to itself is what makes a test suite nest. A simple type gets a node of its own only when it is an enumeration, because its values are what a type name cannot say.

Diagram of TestReport-v0.1.xsd

The types of TestReport-v0.1.xsd, drawn from the schema at documentation build time.

Source

TestReport-v0.1.xsd
  1<?xml version="1.0" encoding="utf-8" ?>
  2<!--
  3	Authors:
  4	  Patrick Lehmann
  5
  6	Copyright 2026-2026 Patrick Lehmann - Bötzingen, Germany
  7
  8	Licensed under the Apache License, Version 2.0 (the "License");
  9	you may not use this file except in compliance with the License.
 10	You may obtain a copy of the License at
 11
 12	  http://www.apache.org/licenses/LICENSE-2.0
 13
 14	Unless required by applicable law or agreed to in writing, software
 15	distributed under the License is distributed on an "AS IS" BASIS,
 16	WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 17	See the License for the specific language governing permissions and
 18	limitations under the License.
 19
 20	SPDX-License-Identifier: Apache-2.0
 21-->
 22<xsd:schema
 23	version="0.1"
 24	xmlns:xsd="http://www.w3.org/2001/XMLSchema">
 25	<xsd:annotation>
 26		<xsd:documentation xml:lang="en">
 27			pyTooling's test report format.
 28
 29			It differs from JUnit XML in two ways that JUnit cannot express: test suites nest, instead of being
 30			flattened into a dotted 'classname'; and every item carries four distinct names - an identifier, a title, a
 31			summary and a description - instead of one name and a bag of properties.
 32		</xsd:documentation>
 33	</xsd:annotation>
 34
 35	<xsd:simpleType name="preservingstring">
 36		<xsd:restriction base="xsd:string">
 37			<xsd:whiteSpace value="preserve" />
 38		</xsd:restriction>
 39	</xsd:simpleType>
 40
 41	<xsd:simpleType name="status">
 42		<xsd:annotation>
 43			<xsd:documentation xml:lang="en">The outcome of a testcase.</xsd:documentation>
 44		</xsd:annotation>
 45		<xsd:restriction base="xsd:string">
 46			<xsd:enumeration value="passed" />
 47			<xsd:enumeration value="failed" />
 48			<xsd:enumeration value="errored" />
 49			<xsd:enumeration value="skipped" />
 50			<xsd:enumeration value="expectedToFail" />
 51			<xsd:enumeration value="unexpectedlyPassed" />
 52		</xsd:restriction>
 53	</xsd:simpleType>
 54
 55	<xsd:group name="names">
 56		<xsd:annotation>
 57			<xsd:documentation xml:lang="en">
 58				The three names an item carries besides its identifier. The identifier is the 'name' attribute.
 59			</xsd:documentation>
 60		</xsd:annotation>
 61		<xsd:sequence>
 62			<xsd:element name="Title" type="xsd:string" minOccurs="0" maxOccurs="1">
 63				<xsd:annotation>
 64					<xsd:documentation xml:lang="en">
 65						A short label, written for a reader rather than for Python.
 66					</xsd:documentation>
 67				</xsd:annotation>
 68			</xsd:element>
 69			<xsd:element name="Summary" type="xsd:string" minOccurs="0" maxOccurs="1">
 70				<xsd:annotation>
 71					<xsd:documentation xml:lang="en">The first paragraph of the item's doc-string.</xsd:documentation>
 72				</xsd:annotation>
 73			</xsd:element>
 74			<xsd:element name="Description" type="preservingstring" minOccurs="0" maxOccurs="1">
 75				<xsd:annotation>
 76					<xsd:documentation xml:lang="en">The item's doc-string, with its line breaks preserved.</xsd:documentation>
 77				</xsd:annotation>
 78			</xsd:element>
 79		</xsd:sequence>
 80	</xsd:group>
 81
 82	<xsd:complexType name="testcase">
 83		<xsd:sequence>
 84			<xsd:group ref="names" />
 85			<xsd:element name="Message" type="preservingstring" minOccurs="0" maxOccurs="1">
 86				<xsd:annotation>
 87					<xsd:documentation xml:lang="en">
 88						Why the testcase did not pass: the failure, error or skip reason.
 89					</xsd:documentation>
 90				</xsd:annotation>
 91			</xsd:element>
 92		</xsd:sequence>
 93		<xsd:attribute name="name" type="xsd:string" use="required" />
 94		<xsd:attribute name="status" type="status" use="required" />
 95		<xsd:attribute name="duration" type="xsd:float" use="optional" />
 96		<xsd:attribute name="nodeID" type="xsd:string" use="optional">
 97			<xsd:annotation>
 98				<xsd:documentation xml:lang="en">
 99					The test runner's own identifier for this testcase, so a reader of the report can re-run it.
100				</xsd:documentation>
101			</xsd:annotation>
102		</xsd:attribute>
103	</xsd:complexType>
104
105	<xsd:complexType name="testsuite">
106		<xsd:sequence>
107			<xsd:group ref="names" />
108			<xsd:element name="Testsuite" type="testsuite" minOccurs="0" maxOccurs="unbounded" />
109			<xsd:element name="Testcase" type="testcase" minOccurs="0" maxOccurs="unbounded" />
110		</xsd:sequence>
111		<xsd:attribute name="name" type="xsd:string" use="required" />
112		<xsd:attribute name="tests" type="xsd:nonNegativeInteger" use="optional" />
113		<xsd:attribute name="duration" type="xsd:float" use="optional" />
114	</xsd:complexType>
115
116	<xsd:complexType name="testreport">
117		<xsd:sequence>
118			<xsd:group ref="names" />
119			<xsd:element name="Testsuite" type="testsuite" minOccurs="0" maxOccurs="unbounded" />
120		</xsd:sequence>
121		<xsd:attribute name="timestamp" type="xsd:dateTime" use="optional" />
122		<xsd:attribute name="duration" type="xsd:float" use="optional" />
123		<xsd:attribute name="tests" type="xsd:nonNegativeInteger" use="optional" />
124		<xsd:attribute name="failures" type="xsd:nonNegativeInteger" use="optional" />
125		<xsd:attribute name="errors" type="xsd:nonNegativeInteger" use="optional" />
126		<xsd:attribute name="skipped" type="xsd:nonNegativeInteger" use="optional" />
127	</xsd:complexType>
128
129	<xsd:element name="TestReport" type="testreport">
130		<xsd:annotation>
131			<xsd:documentation xml:lang="en">The results of one test session.</xsd:documentation>
132		</xsd:annotation>
133	</xsd:element>
134</xsd:schema>