junit-xml-1.7/ 0000755 0000765 0000024 00000000000 12725331541 013021 5 ustar bb staff 0000000 0000000 junit-xml-1.7/junit_xml/ 0000755 0000765 0000024 00000000000 12725331541 015032 5 ustar bb staff 0000000 0000000 junit-xml-1.7/junit_xml/__init__.py 0000644 0000765 0000024 00000027554 12725331533 017161 0 ustar bb staff 0000000 0000000 #!/usr/bin/env python
# -*- coding: UTF-8 -*-
from collections import defaultdict
import sys
import re
import xml.etree.ElementTree as ET
import xml.dom.minidom
from six import u, iteritems, PY2
try:
# Python 2
unichr
except NameError: # pragma: nocover
# Python 3
unichr = chr
"""
Based on the understanding of what Jenkins can parse for JUnit XML files.
the output of the testcase
the output of the testcase
the output of the testcase
I am system output
I am the error output
"""
def decode(var, encoding):
"""
If not already unicode, decode it.
"""
if PY2:
if isinstance(var, unicode):
ret = var
elif isinstance(var, str):
if encoding:
ret = var.decode(encoding)
else:
ret = unicode(var)
else:
ret = unicode(var)
else:
ret = str(var)
return ret
class TestSuite(object):
"""
Suite of test cases.
Can handle unicode strings or binary strings if their encoding is provided.
"""
def __init__(self, name, test_cases=None, hostname=None, id=None,
package=None, timestamp=None, properties=None):
self.name = name
if not test_cases:
test_cases = []
try:
iter(test_cases)
except TypeError:
raise Exception('test_cases must be a list of test cases')
self.test_cases = test_cases
self.hostname = hostname
self.id = id
self.package = package
self.timestamp = timestamp
self.properties = properties
def build_xml_doc(self, encoding=None):
"""
Builds the XML document for the JUnit test suite.
Produces clean unicode strings and decodes non-unicode with the help of encoding.
@param encoding: Used to decode encoded strings.
@return: XML document with unicode string elements
"""
# build the test suite element
test_suite_attributes = dict()
test_suite_attributes['name'] = decode(self.name, encoding)
test_suite_attributes['failures'] = \
str(len([c for c in self.test_cases if c.is_failure()]))
test_suite_attributes['errors'] = \
str(len([c for c in self.test_cases if c.is_error()]))
test_suite_attributes['skipped'] = \
str(len([c for c in self.test_cases if c.is_skipped()]))
test_suite_attributes['time'] = \
str(sum(c.elapsed_sec for c in self.test_cases if c.elapsed_sec))
test_suite_attributes['tests'] = str(len(self.test_cases))
if self.hostname:
test_suite_attributes['hostname'] = decode(self.hostname, encoding)
if self.id:
test_suite_attributes['id'] = decode(self.id, encoding)
if self.package:
test_suite_attributes['package'] = decode(self.package, encoding)
if self.timestamp:
test_suite_attributes['timestamp'] = decode(self.timestamp, encoding)
xml_element = ET.Element("testsuite", test_suite_attributes)
# add any properties
if self.properties:
props_element = ET.SubElement(xml_element, "properties")
for k, v in self.properties.items():
attrs = {'name': decode(k, encoding), 'value': decode(v, encoding)}
ET.SubElement(props_element, "property", attrs)
# test cases
for case in self.test_cases:
test_case_attributes = dict()
test_case_attributes['name'] = decode(case.name, encoding)
if case.elapsed_sec:
test_case_attributes['time'] = "%f" % case.elapsed_sec
if case.classname:
test_case_attributes['classname'] = decode(case.classname, encoding)
test_case_element = ET.SubElement(
xml_element, "testcase", test_case_attributes)
# failures
if case.is_failure():
attrs = {'type': 'failure'}
if case.failure_message:
attrs['message'] = decode(case.failure_message, encoding)
failure_element = ET.Element("failure", attrs)
if case.failure_output:
failure_element.text = decode(case.failure_output, encoding)
test_case_element.append(failure_element)
# errors
if case.is_error():
attrs = {'type': 'error'}
if case.error_message:
attrs['message'] = decode(case.error_message, encoding)
error_element = ET.Element("error", attrs)
if case.error_output:
error_element.text = decode(case.error_output, encoding)
test_case_element.append(error_element)
# skippeds
if case.is_skipped():
attrs = {'type': 'skipped'}
if case.skipped_message:
attrs['message'] = decode(case.skipped_message, encoding)
skipped_element = ET.Element("skipped", attrs)
if case.skipped_output:
skipped_element.text = decode(case.skipped_output, encoding)
test_case_element.append(skipped_element)
# test stdout
if case.stdout:
stdout_element = ET.Element("system-out")
stdout_element.text = decode(case.stdout, encoding)
test_case_element.append(stdout_element)
# test stderr
if case.stderr:
stderr_element = ET.Element("system-err")
stderr_element.text = decode(case.stderr, encoding)
test_case_element.append(stderr_element)
return xml_element
@staticmethod
def to_xml_string(test_suites, prettyprint=True, encoding=None):
"""
Returns the string representation of the JUnit XML document.
@param encoding: The encoding of the input.
@return: unicode string
"""
try:
iter(test_suites)
except TypeError:
raise Exception('test_suites must be a list of test suites')
xml_element = ET.Element("testsuites")
attributes = defaultdict(int)
for ts in test_suites:
ts_xml = ts.build_xml_doc(encoding=encoding)
for key in ['failures', 'errors', 'tests']:
attributes[key] += int(ts_xml.get(key, 0))
for key in ['time']:
attributes[key] += float(ts_xml.get(key, 0))
xml_element.append(ts_xml)
for key, value in iteritems(attributes):
xml_element.set(key, str(value))
xml_string = ET.tostring(xml_element, encoding=encoding)
# is encoded now
xml_string = TestSuite._clean_illegal_xml_chars(
xml_string.decode(encoding or 'utf-8'))
# is unicode now
if prettyprint:
# minidom.parseString() works just on correctly encoded binary strings
xml_string = xml_string.encode(encoding or 'utf-8')
xml_string = xml.dom.minidom.parseString(xml_string)
# toprettyxml() produces unicode if no encoding is being passed or binary string with an encoding
xml_string = xml_string.toprettyxml(encoding=encoding)
if encoding:
xml_string = xml_string.decode(encoding)
# is unicode now
return xml_string
@staticmethod
def to_file(file_descriptor, test_suites, prettyprint=True, encoding=None):
"""
Writes the JUnit XML document to a file.
"""
xml_string = TestSuite.to_xml_string(
test_suites, prettyprint=prettyprint, encoding=encoding)
# has problems with encoded str with non-ASCII (non-default-encoding) characters!
file_descriptor.write(xml_string)
@staticmethod
def _clean_illegal_xml_chars(string_to_clean):
"""
Removes any illegal unicode characters from the given XML string.
@see: http://stackoverflow.com/questions/1707890/fast-way-to-filter-illegal-xml-unicode-chars-in-python
"""
illegal_unichrs = [
(0x00, 0x08), (0x0B, 0x1F), (0x7F, 0x84), (0x86, 0x9F),
(0xD800, 0xDFFF), (0xFDD0, 0xFDDF), (0xFFFE, 0xFFFF),
(0x1FFFE, 0x1FFFF), (0x2FFFE, 0x2FFFF), (0x3FFFE, 0x3FFFF),
(0x4FFFE, 0x4FFFF), (0x5FFFE, 0x5FFFF), (0x6FFFE, 0x6FFFF),
(0x7FFFE, 0x7FFFF), (0x8FFFE, 0x8FFFF), (0x9FFFE, 0x9FFFF),
(0xAFFFE, 0xAFFFF), (0xBFFFE, 0xBFFFF), (0xCFFFE, 0xCFFFF),
(0xDFFFE, 0xDFFFF), (0xEFFFE, 0xEFFFF), (0xFFFFE, 0xFFFFF),
(0x10FFFE, 0x10FFFF)]
illegal_ranges = ["%s-%s" % (unichr(low), unichr(high))
for (low, high) in illegal_unichrs
if low < sys.maxunicode]
illegal_xml_re = re.compile(u('[%s]') % u('').join(illegal_ranges))
return illegal_xml_re.sub('', string_to_clean)
class TestCase(object):
"""A JUnit test case with a result and possibly some stdout or stderr"""
def __init__(self, name, classname=None, elapsed_sec=None, stdout=None,
stderr=None):
self.name = name
self.elapsed_sec = elapsed_sec
self.stdout = stdout
self.stderr = stderr
self.classname = classname
self.error_message = None
self.error_output = None
self.failure_message = None
self.failure_output = None
self.skipped_message = None
self.skipped_output = None
def add_error_info(self, message=None, output=None):
"""Adds an error message, output, or both to the test case"""
if message:
self.error_message = message
if output:
self.error_output = output
def add_failure_info(self, message=None, output=None):
"""Adds a failure message, output, or both to the test case"""
if message:
self.failure_message = message
if output:
self.failure_output = output
def add_skipped_info(self, message=None, output=None):
"""Adds a skipped message, output, or both to the test case"""
if message:
self.skipped_message = message
if output:
self.skipped_output = output
def is_failure(self):
"""returns true if this test case is a failure"""
return self.failure_output or self.failure_message
def is_error(self):
"""returns true if this test case is an error"""
return self.error_output or self.error_message
def is_skipped(self):
"""returns true if this test case has been skipped"""
return self.skipped_output or self.skipped_message
junit-xml-1.7/junit_xml.egg-info/ 0000755 0000765 0000024 00000000000 12725331541 016524 5 ustar bb staff 0000000 0000000 junit-xml-1.7/junit_xml.egg-info/dependency_links.txt 0000644 0000765 0000024 00000000001 12725331541 022572 0 ustar bb staff 0000000 0000000
junit-xml-1.7/junit_xml.egg-info/PKG-INFO 0000644 0000765 0000024 00000007372 12725331541 017632 0 ustar bb staff 0000000 0000000 Metadata-Version: 1.1
Name: junit-xml
Version: 1.7
Summary: Creates JUnit XML test result documents that can be read by tools such as Jenkins
Home-page: https://github.com/kyrus/python-junit-xml
Author: Brian Beyer
Author-email: brian@kyr.us
License: MIT
Description: python-junit-xml
================
.. image:: https://travis-ci.org/kyrus/python-junit-xml.png?branch=master
About
-----
A Python module for creating JUnit XML test result documents that can be
read by tools such as Jenkins. If you are ever working with test tool or
test suite written in Python and want to take advantage of Jenkins'
pretty graphs and test reporting capabilities, this module will let you
generate the XML test reports.
*As there is no definitive Jenkins JUnit XSD that I could find, the XML
documents created by this module support a schema based on Google
searches and the Jenkins JUnit XML reader source code. File a bug if
something doesn't work like you expect it to.*
Installation
------------
Install using pip or easy_install:
::
pip install junit-xml
or
easy_install junit-xml
You can also clone the Git repository from Github and install it manually:
::
git clone https://github.com/kyrus/python-junit-xml.git
python setup.py install
Using
-----
Create a test suite, add a test case, and print it to the screen:
.. code-block:: python
from junit_xml import TestSuite, TestCase
test_cases = [TestCase('Test1', 'some.class.name', 123.345, 'I am stdout!', 'I am stderr!')]
ts = TestSuite("my test suite", test_cases)
# pretty printing is on by default but can be disabled using prettyprint=False
print(TestSuite.to_xml_string([ts]))
Produces the following output
.. code-block:: xml
I am stdout!
I am stderr!
Writing XML to a file:
.. code-block:: python
# you can also write the XML to a file and not pretty print it
with open('output.xml', 'w') as f:
TestSuite.to_file(f, [ts], prettyprint=False)
See the docs and unit tests for more examples.
NOTE: Unicode characters identified as "illegal or discouraged" are automatically
stripped from the XML string or file.
Running the tests
-----------------
::
# activate your virtualenv
pip install tox
tox
Platform: UNKNOWN
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: License :: Freely Distributable
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Software Development :: Build Tools
Classifier: Topic :: Software Development :: Testing
junit-xml-1.7/junit_xml.egg-info/requires.txt 0000644 0000765 0000024 00000000003 12725331541 021115 0 ustar bb staff 0000000 0000000 six junit-xml-1.7/junit_xml.egg-info/SOURCES.txt 0000644 0000765 0000024 00000000377 12725331541 020417 0 ustar bb staff 0000000 0000000 LICENSE.txt
MANIFEST.in
README.rst
setup.py
test_junit_xml.py
tox.ini
junit_xml/__init__.py
junit_xml.egg-info/PKG-INFO
junit_xml.egg-info/SOURCES.txt
junit_xml.egg-info/dependency_links.txt
junit_xml.egg-info/requires.txt
junit_xml.egg-info/top_level.txt junit-xml-1.7/junit_xml.egg-info/top_level.txt 0000644 0000765 0000024 00000000012 12725331541 021247 0 ustar bb staff 0000000 0000000 junit_xml
junit-xml-1.7/LICENSE.txt 0000644 0000765 0000024 00000002101 12704613356 014642 0 ustar bb staff 0000000 0000000 The MIT License
Copyright (c) 2013 Kyrus Tech, Inc., Brian Beyer
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE. junit-xml-1.7/MANIFEST.in 0000644 0000765 0000024 00000000142 12704613356 014560 0 ustar bb staff 0000000 0000000 include LICENSE.txt
include README.rst
include setup.py
include test_junit_xml.py
include tox.ini
junit-xml-1.7/PKG-INFO 0000644 0000765 0000024 00000007372 12725331541 014127 0 ustar bb staff 0000000 0000000 Metadata-Version: 1.1
Name: junit-xml
Version: 1.7
Summary: Creates JUnit XML test result documents that can be read by tools such as Jenkins
Home-page: https://github.com/kyrus/python-junit-xml
Author: Brian Beyer
Author-email: brian@kyr.us
License: MIT
Description: python-junit-xml
================
.. image:: https://travis-ci.org/kyrus/python-junit-xml.png?branch=master
About
-----
A Python module for creating JUnit XML test result documents that can be
read by tools such as Jenkins. If you are ever working with test tool or
test suite written in Python and want to take advantage of Jenkins'
pretty graphs and test reporting capabilities, this module will let you
generate the XML test reports.
*As there is no definitive Jenkins JUnit XSD that I could find, the XML
documents created by this module support a schema based on Google
searches and the Jenkins JUnit XML reader source code. File a bug if
something doesn't work like you expect it to.*
Installation
------------
Install using pip or easy_install:
::
pip install junit-xml
or
easy_install junit-xml
You can also clone the Git repository from Github and install it manually:
::
git clone https://github.com/kyrus/python-junit-xml.git
python setup.py install
Using
-----
Create a test suite, add a test case, and print it to the screen:
.. code-block:: python
from junit_xml import TestSuite, TestCase
test_cases = [TestCase('Test1', 'some.class.name', 123.345, 'I am stdout!', 'I am stderr!')]
ts = TestSuite("my test suite", test_cases)
# pretty printing is on by default but can be disabled using prettyprint=False
print(TestSuite.to_xml_string([ts]))
Produces the following output
.. code-block:: xml
I am stdout!
I am stderr!
Writing XML to a file:
.. code-block:: python
# you can also write the XML to a file and not pretty print it
with open('output.xml', 'w') as f:
TestSuite.to_file(f, [ts], prettyprint=False)
See the docs and unit tests for more examples.
NOTE: Unicode characters identified as "illegal or discouraged" are automatically
stripped from the XML string or file.
Running the tests
-----------------
::
# activate your virtualenv
pip install tox
tox
Platform: UNKNOWN
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: License :: Freely Distributable
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Software Development :: Build Tools
Classifier: Topic :: Software Development :: Testing
junit-xml-1.7/README.rst 0000644 0000765 0000024 00000004520 12704613356 014515 0 ustar bb staff 0000000 0000000 python-junit-xml
================
.. image:: https://travis-ci.org/kyrus/python-junit-xml.png?branch=master
About
-----
A Python module for creating JUnit XML test result documents that can be
read by tools such as Jenkins. If you are ever working with test tool or
test suite written in Python and want to take advantage of Jenkins'
pretty graphs and test reporting capabilities, this module will let you
generate the XML test reports.
*As there is no definitive Jenkins JUnit XSD that I could find, the XML
documents created by this module support a schema based on Google
searches and the Jenkins JUnit XML reader source code. File a bug if
something doesn't work like you expect it to.*
Installation
------------
Install using pip or easy_install:
::
pip install junit-xml
or
easy_install junit-xml
You can also clone the Git repository from Github and install it manually:
::
git clone https://github.com/kyrus/python-junit-xml.git
python setup.py install
Using
-----
Create a test suite, add a test case, and print it to the screen:
.. code-block:: python
from junit_xml import TestSuite, TestCase
test_cases = [TestCase('Test1', 'some.class.name', 123.345, 'I am stdout!', 'I am stderr!')]
ts = TestSuite("my test suite", test_cases)
# pretty printing is on by default but can be disabled using prettyprint=False
print(TestSuite.to_xml_string([ts]))
Produces the following output
.. code-block:: xml
I am stdout!
I am stderr!
Writing XML to a file:
.. code-block:: python
# you can also write the XML to a file and not pretty print it
with open('output.xml', 'w') as f:
TestSuite.to_file(f, [ts], prettyprint=False)
See the docs and unit tests for more examples.
NOTE: Unicode characters identified as "illegal or discouraged" are automatically
stripped from the XML string or file.
Running the tests
-----------------
::
# activate your virtualenv
pip install tox
tox
junit-xml-1.7/setup.cfg 0000644 0000765 0000024 00000000073 12725331541 014642 0 ustar bb staff 0000000 0000000 [egg_info]
tag_build =
tag_date = 0
tag_svn_revision = 0
junit-xml-1.7/setup.py 0000644 0000765 0000024 00000002076 12725331533 014541 0 ustar bb staff 0000000 0000000 #!/usr/bin/env python
from setuptools import setup, find_packages
import os
def read(fname):
return open(os.path.join(os.path.dirname(__file__), fname)).read()
setup(
name='junit-xml',
author='Brian Beyer',
author_email='brian@kyr.us',
url='https://github.com/kyrus/python-junit-xml',
license='MIT',
packages=find_packages(),
test_suite='test_junit_xml',
description='Creates JUnit XML test result documents that can be read by '
'tools such as Jenkins',
long_description=read('README.rst'),
version='1.7',
classifiers=[
'Development Status :: 5 - Production/Stable',
'Intended Audience :: Developers',
'License :: Freely Distributable',
'License :: OSI Approved :: MIT License',
'Operating System :: OS Independent',
'Programming Language :: Python',
'Programming Language :: Python :: 3',
'Topic :: Software Development :: Build Tools',
'Topic :: Software Development :: Testing',
],
install_requires=[
'six'
]
)
junit-xml-1.7/test_junit_xml.py 0000644 0000765 0000024 00000046534 12725331533 016460 0 ustar bb staff 0000000 0000000 # -*- coding: UTF-8 -*-
from __future__ import with_statement
import unittest
import os
import tempfile
import textwrap
from xml.dom import minidom
import codecs
from six import u, PY2
from junit_xml import TestCase, TestSuite, decode
def serialize_and_read(test_suites, to_file=False, prettyprint=False, encoding=None):
"""writes the test suite to an XML string and then re-reads it using minidom,
returning => (test suite element, list of test case elements)"""
try:
iter(test_suites)
except TypeError:
test_suites = [test_suites]
if to_file:
fd, filename = tempfile.mkstemp(text=True)
os.close(fd)
with codecs.open(filename, mode='w', encoding=encoding) as f:
TestSuite.to_file(f, test_suites, prettyprint=prettyprint, encoding=encoding)
print("Serialized XML to temp file [%s]" % filename)
xmldoc = minidom.parse(filename)
os.remove(filename)
else:
xml_string = TestSuite.to_xml_string(
test_suites, prettyprint=prettyprint, encoding=encoding)
if PY2:
assert isinstance(xml_string, unicode)
print("Serialized XML to string:\n%s" % xml_string)
if encoding:
xml_string = xml_string.encode(encoding)
xmldoc = minidom.parseString(xml_string)
def remove_blanks(node):
for x in node.childNodes:
if x.nodeType == minidom.Node.TEXT_NODE:
if x.nodeValue:
x.nodeValue = x.nodeValue.strip()
elif x.nodeType == minidom.Node.ELEMENT_NODE:
remove_blanks(x)
remove_blanks(xmldoc)
xmldoc.normalize()
ret = []
suites = xmldoc.getElementsByTagName("testsuites")[0]
for suite in suites.getElementsByTagName("testsuite"):
cases = suite.getElementsByTagName("testcase")
ret.append((suite, cases))
return ret
class TestSuiteTests(unittest.TestCase):
def test_single_suite_single_test_case(self):
try:
(ts, tcs) = serialize_and_read(
TestSuite('test', TestCase('Test1')), to_file=True)[0]
self.fail("This should've raised an exeception") # pragma: nocover
except Exception as exc:
self.assertEqual(
str(exc), 'test_cases must be a list of test cases')
def test_single_suite_no_test_cases(self):
properties = {'foo': 'bar'}
package = 'mypackage'
timestamp = 1398382805
(ts, tcs) = serialize_and_read(
TestSuite(
'test',
[],
hostname='localhost',
id=1,
properties=properties,
package=package,
timestamp=timestamp
),
to_file=True,
prettyprint=True
)[0]
self.assertEqual(ts.tagName, 'testsuite')
self.assertEqual(ts.attributes['package'].value, package)
self.assertEqual(ts.attributes['timestamp'].value, str(timestamp))
self.assertEqual(
ts.childNodes[0].childNodes[0].attributes['name'].value,
'foo')
self.assertEqual(
ts.childNodes[0].childNodes[0].attributes['value'].value,
'bar')
def test_single_suite_no_test_cases_utf8(self):
properties = {'foö': 'bär'}
package = 'mypäckage'
timestamp = 1398382805
test_suite = TestSuite(
'äöü',
[],
hostname='löcalhost',
id='äöü',
properties=properties,
package=package,
timestamp=timestamp
)
(ts, tcs) = serialize_and_read(
test_suite,
to_file=True,
prettyprint=True,
encoding='utf-8'
)[0]
self.assertEqual(ts.tagName, 'testsuite')
self.assertEqual(ts.attributes['package'].value, decode(package, 'utf-8'))
self.assertEqual(ts.attributes['timestamp'].value, str(timestamp))
self.assertEqual(
ts.childNodes[0].childNodes[0].attributes['name'].value,
decode('foö', 'utf-8'))
self.assertEqual(
ts.childNodes[0].childNodes[0].attributes['value'].value,
decode('bär', 'utf-8'))
def test_single_suite_no_test_cases_unicode(self):
properties = {decode('foö', 'utf-8'): decode('bär', 'utf-8')}
package = decode('mypäckage', 'utf-8')
timestamp = 1398382805
(ts, tcs) = serialize_and_read(
TestSuite(
decode('äöü', 'utf-8'),
[],
hostname=decode('löcalhost', 'utf-8'),
id=decode('äöü', 'utf-8'),
properties=properties,
package=package,
timestamp=timestamp
),
to_file=True,
prettyprint=True,
encoding='utf-8'
)[0]
self.assertEqual(ts.tagName, 'testsuite')
self.assertEqual(ts.attributes['package'].value, package)
self.assertEqual(ts.attributes['timestamp'].value, str(timestamp))
self.assertEqual(
ts.childNodes[0].childNodes[0].attributes['name'].value,
decode('foö', 'utf-8'))
self.assertEqual(
ts.childNodes[0].childNodes[0].attributes['value'].value,
decode('bär', 'utf-8'))
def test_single_suite_to_file(self):
(ts, tcs) = serialize_and_read(
TestSuite('test', [TestCase('Test1')]), to_file=True)[0]
verify_test_case(self, tcs[0], {'name': 'Test1'})
def test_single_suite_to_file_prettyprint(self):
(ts, tcs) = serialize_and_read(TestSuite(
'test', [TestCase('Test1')]), to_file=True, prettyprint=True)[0]
verify_test_case(self, tcs[0], {'name': 'Test1'})
def test_single_suite_prettyprint(self):
(ts, tcs) = serialize_and_read(
TestSuite('test', [TestCase('Test1')]),
to_file=False, prettyprint=True)[0]
verify_test_case(self, tcs[0], {'name': 'Test1'})
def test_single_suite_to_file_no_prettyprint(self):
(ts, tcs) = serialize_and_read(
TestSuite('test', [TestCase('Test1')]),
to_file=True, prettyprint=False)[0]
verify_test_case(self, tcs[0], {'name': 'Test1'})
def test_multiple_suites_to_file(self):
tss = [TestSuite('suite1', [TestCase('Test1')]),
TestSuite('suite2', [TestCase('Test2')])]
suites = serialize_and_read(tss, to_file=True)
self.assertEqual('suite1', suites[0][0].attributes['name'].value)
verify_test_case(self, suites[0][1][0], {'name': 'Test1'})
self.assertEqual('suite2', suites[1][0].attributes['name'].value)
verify_test_case(self, suites[1][1][0], {'name': 'Test2'})
def test_multiple_suites_to_string(self):
tss = [TestSuite('suite1', [TestCase('Test1')]),
TestSuite('suite2', [TestCase('Test2')])]
suites = serialize_and_read(tss)
self.assertEqual('suite1', suites[0][0].attributes['name'].value)
verify_test_case(self, suites[0][1][0], {'name': 'Test1'})
self.assertEqual('suite2', suites[1][0].attributes['name'].value)
verify_test_case(self, suites[1][1][0], {'name': 'Test2'})
def test_attribute_time(self):
tss = [TestSuite('suite1',
[TestCase('Test1', 'some.class.name', 123.345),
TestCase('Test2', 'some2.class.name', 123.345)]),
TestSuite('suite2', [TestCase('Test2')])]
suites = serialize_and_read(tss)
self.assertEqual('suite1', suites[0][0].attributes['name'].value)
self.assertEqual('246.69', suites[0][0].attributes['time'].value)
self.assertEqual('suite2', suites[1][0].attributes['name'].value)
# here the time in testsuite is "0" even there is no attribute time for
# testcase
self.assertEqual('0', suites[1][0].attributes['time'].value)
# @todo: add more tests for the other attributes and properties
def test_to_xml_string(self):
test_suites = [TestSuite('suite1', [TestCase('Test1')]),
TestSuite('suite2', [TestCase('Test2')])]
xml_string = TestSuite.to_xml_string(test_suites)
if PY2:
self.assertTrue(isinstance(xml_string, unicode))
expected_xml_string = textwrap.dedent("""
\t
\t\t
\t
\t
\t\t
\t
""".strip("\n")) # NOQA
self.assertEqual(xml_string, expected_xml_string)
def test_to_xml_string_test_suites_not_a_list(self):
test_suites = TestSuite('suite1', [TestCase('Test1')])
try:
TestSuite.to_xml_string(test_suites)
except Exception as exc:
self.assertEqual(
str(exc), 'test_suites must be a list of test suites')
class TestCaseTests(unittest.TestCase):
def test_init(self):
(ts, tcs) = serialize_and_read(
TestSuite('test', [TestCase('Test1')]))[0]
verify_test_case(self, tcs[0], {'name': 'Test1'})
def test_init_classname(self):
(ts, tcs) = serialize_and_read(
TestSuite('test', [TestCase('Test1', 'some.class.name')]))[0]
verify_test_case(
self, tcs[0], {'name': 'Test1', 'classname': 'some.class.name'})
def test_init_classname_time(self):
(ts, tcs) = serialize_and_read(
TestSuite('test',
[TestCase('Test1', 'some.class.name', 123.345)]))[0]
verify_test_case(
self, tcs[0], {'name': 'Test1', 'classname': 'some.class.name',
'time': ("%f" % 123.345)})
def test_init_stderr(self):
(ts, tcs) = serialize_and_read(
TestSuite(
'test', [TestCase('Test1', 'some.class.name', 123.345,
stderr='I am stderr!')]))[0]
verify_test_case(
self, tcs[0],
{'name': 'Test1', 'classname': 'some.class.name',
'time': ("%f" % 123.345)}, stderr='I am stderr!')
def test_init_stdout_stderr(self):
(ts, tcs) = serialize_and_read(
TestSuite(
'test', [TestCase(
'Test1', 'some.class.name', 123.345, 'I am stdout!',
'I am stderr!')]))[0]
verify_test_case(
self, tcs[0],
{'name': 'Test1', 'classname': 'some.class.name',
'time': ("%f" % 123.345)},
stdout='I am stdout!', stderr='I am stderr!')
def test_init_failure_message(self):
tc = TestCase('Failure-Message')
tc.add_failure_info("failure message")
(ts, tcs) = serialize_and_read(TestSuite('test', [tc]))[0]
verify_test_case(
self, tcs[0], {'name': 'Failure-Message'},
failure_message="failure message")
def test_init_failure_output(self):
tc = TestCase('Failure-Output')
tc.add_failure_info(output="I failed!")
(ts, tcs) = serialize_and_read(TestSuite('test', [tc]))[0]
verify_test_case(
self, tcs[0], {'name': 'Failure-Output'},
failure_output="I failed!")
def test_init_failure(self):
tc = TestCase('Failure-Message-and-Output')
tc.add_failure_info("failure message", "I failed!")
(ts, tcs) = serialize_and_read(TestSuite('test', [tc]))[0]
verify_test_case(
self, tcs[0], {'name': 'Failure-Message-and-Output'},
failure_message="failure message", failure_output="I failed!")
def test_init_error_message(self):
tc = TestCase('Error-Message')
tc.add_error_info("error message")
(ts, tcs) = serialize_and_read(TestSuite('test', [tc]))[0]
verify_test_case(
self, tcs[0], {'name': 'Error-Message'},
error_message="error message")
def test_init_error_output(self):
tc = TestCase('Error-Output')
tc.add_error_info(output="I errored!")
(ts, tcs) = serialize_and_read(TestSuite('test', [tc]))[0]
verify_test_case(
self, tcs[0], {'name': 'Error-Output'}, error_output="I errored!")
def test_init_error(self):
tc = TestCase('Error-Message-and-Output')
tc.add_error_info("error message", "I errored!")
(ts, tcs) = serialize_and_read(TestSuite('test', [tc]))[0]
verify_test_case(
self, tcs[0], {'name': 'Error-Message-and-Output'},
error_message="error message", error_output="I errored!")
def test_init_skipped_message(self):
tc = TestCase('Skipped-Message')
tc.add_skipped_info("skipped message")
(ts, tcs) = serialize_and_read(TestSuite('test', [tc]))[0]
verify_test_case(
self, tcs[0], {'name': 'Skipped-Message'},
skipped_message="skipped message")
def test_init_skipped_output(self):
tc = TestCase('Skipped-Output')
tc.add_skipped_info(output="I skipped!")
(ts, tcs) = serialize_and_read(TestSuite('test', [tc]))[0]
verify_test_case(
self, tcs[0], {'name': 'Skipped-Output'},
skipped_output="I skipped!")
def test_init_skipped_err_output(self):
tc = TestCase('Skipped-Output')
tc.add_skipped_info(output="I skipped!")
tc.add_error_info(output="I skipped with an error!")
(ts, tcs) = serialize_and_read(TestSuite('test', [tc]))[0]
verify_test_case(
self, tcs[0],
{'name': 'Skipped-Output'},
skipped_output="I skipped!",
error_output="I skipped with an error!")
def test_init_skipped(self):
tc = TestCase('Skipped-Message-and-Output')
tc.add_skipped_info("skipped message", "I skipped!")
(ts, tcs) = serialize_and_read(TestSuite('test', [tc]))[0]
verify_test_case(
self, tcs[0], {'name': 'Skipped-Message-and-Output'},
skipped_message="skipped message", skipped_output="I skipped!")
def test_init_legal_unicode_char(self):
tc = TestCase('Failure-Message')
tc.add_failure_info(
u("failure message with legal unicode char: [\x22]"))
(ts, tcs) = serialize_and_read(TestSuite('test', [tc]))[0]
verify_test_case(
self, tcs[0], {'name': 'Failure-Message'}, failure_message=u(
"failure message with legal unicode char: [\x22]"))
def test_init_illegal_unicode_char(self):
tc = TestCase('Failure-Message')
tc.add_failure_info(
u("failure message with illegal unicode char: [\x02]"))
(ts, tcs) = serialize_and_read(TestSuite('test', [tc]))[0]
verify_test_case(
self, tcs[0], {'name': 'Failure-Message'}, failure_message=u(
"failure message with illegal unicode char: []"))
def test_init_utf8(self):
tc = TestCase('Test äöü', 'some.class.name.äöü', 123.345, 'I am stdöüt!', 'I am stdärr!')
tc.add_skipped_info(message='Skipped äöü', output="I skippäd!")
tc.add_error_info(message='Skipped error äöü', output="I skippäd with an error!")
test_suite = TestSuite('Test UTF-8', [tc])
(ts, tcs) = serialize_and_read(test_suite, encoding='utf-8')[0]
verify_test_case(self, tcs[0], {'name': decode('Test äöü', 'utf-8'),
'classname': decode('some.class.name.äöü', 'utf-8'),
'time': ("%f" % 123.345)},
stdout=decode('I am stdöüt!', 'utf-8'), stderr=decode('I am stdärr!', 'utf-8'),
skipped_message=decode('Skipped äöü', 'utf-8'),
skipped_output=decode('I skippäd!', 'utf-8'),
error_message=decode('Skipped error äöü', 'utf-8'),
error_output=decode('I skippäd with an error!', 'utf-8'))
def test_init_unicode(self):
tc = TestCase(decode('Test äöü', 'utf-8'), decode('some.class.name.äöü', 'utf-8'), 123.345,
decode('I am stdöüt!', 'utf-8'), decode('I am stdärr!', 'utf-8'))
tc.add_skipped_info(message=decode('Skipped äöü', 'utf-8'),
output=decode('I skippäd!', 'utf-8'))
tc.add_error_info(message=decode('Skipped error äöü', 'utf-8'),
output=decode('I skippäd with an error!', 'utf-8'))
(ts, tcs) = serialize_and_read(TestSuite('Test Unicode',
[tc]))[0]
verify_test_case(self, tcs[0], {'name': decode('Test äöü', 'utf-8'),
'classname': decode('some.class.name.äöü', 'utf-8'),
'time': ("%f" % 123.345)},
stdout=decode('I am stdöüt!', 'utf-8'), stderr=decode('I am stdärr!', 'utf-8'),
skipped_message=decode('Skipped äöü', 'utf-8'),
skipped_output=decode('I skippäd!', 'utf-8'),
error_message=decode('Skipped error äöü', 'utf-8'),
error_output=decode('I skippäd with an error!', 'utf-8'))
def verify_test_case(tc, test_case_element, expected_attributes,
error_message=None, error_output=None,
failure_message=None, failure_output=None,
skipped_message=None, skipped_output=None,
stdout=None, stderr=None):
for k, v in expected_attributes.items():
tc.assertEqual(v, test_case_element.attributes[k].value)
for k in test_case_element.attributes.keys():
tc.assertTrue(k in expected_attributes.keys())
if stderr:
tc.assertEqual(
stderr, test_case_element.getElementsByTagName(
'system-err')[0].firstChild.nodeValue.strip())
if stdout:
tc.assertEqual(
stdout, test_case_element.getElementsByTagName(
'system-out')[0].firstChild.nodeValue.strip())
errors = test_case_element.getElementsByTagName('error')
if error_message or error_output:
tc.assertTrue(len(errors) > 0)
else:
tc.assertEqual(0, len(errors))
if error_message:
tc.assertEqual(
error_message, errors[0].attributes['message'].value)
if error_output:
tc.assertEqual(
error_output, errors[0].firstChild.nodeValue.strip())
failures = test_case_element.getElementsByTagName('failure')
if failure_message or failure_output:
tc.assertTrue(len(failures) > 0)
else:
tc.assertEqual(0, len(failures))
if failure_message:
tc.assertEqual(
failure_message, failures[0].attributes['message'].value)
if failure_output:
tc.assertEqual(
failure_output, failures[0].firstChild.nodeValue.strip())
skipped = test_case_element.getElementsByTagName('skipped')
if skipped_message or skipped_output:
tc.assertTrue(len(skipped) > 0)
else:
tc.assertEqual(0, len(skipped))
if __name__ == '__main__':
unittest.main()
junit-xml-1.7/tox.ini 0000644 0000765 0000024 00000001145 12704613356 014341 0 ustar bb staff 0000000 0000000 [tox]
envlist = py26, py27, pypy, py32, py33, py34, cover, flake8
sitepackages = False
[testenv]
deps =
pytest
pytest-sugar
six
commands =
py.test \
--junitxml={envlogdir}/junit-{envname}.xml \
{posargs}
[testenv:cover]
deps =
pytest
pytest-sugar
pytest-cov
six
commands =
py.test \
--cov=junit_xml \
--cov-report=term-missing \
--cov-report=xml \
--cov-report=html \
{posargs}
[testenv:flake8]
deps =
pytest
pytest-sugar
pytest-flake8
six
commands =
py.test \
--flake8 \
{posargs}