Skip to content

Commit

Permalink
Merge pull request #1454 from tareqalayan/add-global-properties-node
Browse files Browse the repository at this point in the history
junitxml: add properties node in testsuite level
  • Loading branch information
nicoddemus committed Mar 16, 2016
2 parents 5fd8207 + fa6acdc commit ceacc12
Show file tree
Hide file tree
Showing 5 changed files with 111 additions and 0 deletions.
1 change: 1 addition & 0 deletions AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ Ronny Pfannschmidt
Ross Lawley
Ryan Wooden
Samuele Pedroni
Tareq Alayan
Tom Viner
Trevor Bekolay
Wouter van Ackooy
Expand Down
7 changes: 7 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@
tests.
Thanks `@kalekundert`_ for the complete PR (`#1441`_).

* New Add ability to add global properties in the final xunit output file.
Thanks `@tareqalayan`_ for the complete PR `#1454`_).


*

**Changes**
Expand All @@ -28,10 +32,13 @@
.. _@milliams: https://github.com/milliams
.. _@novas0x2a: https://github.com/novas0x2a
.. _@kalekundert: https://github.com/kalekundert
.. _@tareqalayan: https://github.com/tareqalayan

.. _#1428: https://github.com/pytest-dev/pytest/pull/1428
.. _#1444: https://github.com/pytest-dev/pytest/pull/1444
.. _#1441: https://github.com/pytest-dev/pytest/pull/1441
.. _#1454: https://github.com/pytest-dev/pytest/pull/1454


2.9.1.dev1
==========
Expand Down
21 changes: 21 additions & 0 deletions _pytest/junitxml.py
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,7 @@ def __init__(self, logfile, prefix):
], 0)
self.node_reporters = {} # nodeid -> _NodeReporter
self.node_reporters_ordered = []
self.global_properties = []

def finalize(self, report):
nodeid = getattr(report, 'nodeid', report)
Expand All @@ -273,9 +274,12 @@ def node_reporter(self, report):
if key in self.node_reporters:
# TODO: breasks for --dist=each
return self.node_reporters[key]

reporter = _NodeReporter(nodeid, self)

self.node_reporters[key] = reporter
self.node_reporters_ordered.append(reporter)

return reporter

def add_stats(self, key):
Expand Down Expand Up @@ -361,7 +365,9 @@ def pytest_sessionfinish(self):
numtests = self.stats['passed'] + self.stats['failure']

logfile.write('<?xml version="1.0" encoding="utf-8"?>')

logfile.write(Junit.testsuite(
self._get_global_properties_node(),
[x.to_xml() for x in self.node_reporters_ordered],
name="pytest",
errors=self.stats['error'],
Expand All @@ -374,3 +380,18 @@ def pytest_sessionfinish(self):
def pytest_terminal_summary(self, terminalreporter):
terminalreporter.write_sep("-",
"generated xml file: %s" % (self.logfile))

def add_global_property(self, name, value):
self.global_properties.append((str(name), bin_xml_escape(value)))

def _get_global_properties_node(self):
"""Return a Junit node containing custom properties, if any.
"""
if self.global_properties:
return Junit.properties(
[
Junit.property(name=name, value=value)
for name, value in self.global_properties
]
)
return ''
47 changes: 47 additions & 0 deletions doc/en/usage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,53 @@ This will add an extra property ``example_key="1"`` to the generated
Also please note that using this feature will break any schema verification.
This might be a problem when used with some CI servers.

LogXML: add_global_property
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

.. versionadded:: 2.10

If you want to add a properties node in the testsuite level, which may contains properties that are relevant
to all testcases you can use ``LogXML.add_global_properties``

.. code-block:: python
import pytest
@pytest.fixture(scope="session")
def log_global_env_facts(f):
if pytest.config.pluginmanager.hasplugin('junitxml'):
my_junit = getattr(pytest.config, '_xml', None)
my_junit.add_global_property('ARCH', 'PPC')
my_junit.add_global_property('STORAGE_TYPE', 'CEPH')
@pytest.mark.usefixtures(log_global_env_facts)
def start_and_prepare_env():
pass
class TestMe:
def test_foo(self):
assert True
This will add a property node below the testsuite node to the generated xml:

.. code-block:: xml
<testsuite errors="0" failures="0" name="pytest" skips="0" tests="1" time="0.006">
<properties>
<property name="ARCH" value="PPC"/>
<property name="STORAGE_TYPE" value="CEPH"/>
</properties>
<testcase classname="test_me.TestMe" file="test_me.py" line="16" name="test_foo" time="0.000243663787842"/>
</testsuite>
.. warning::

This is an experimental feature, and its interface might be replaced
by something more powerful and general in future versions. The
functionality per-se will be kept.

Creating resultlog format files
----------------------------------------------------

Expand Down
35 changes: 35 additions & 0 deletions testing/test_junitxml.py
Original file line number Diff line number Diff line change
Expand Up @@ -783,3 +783,38 @@ def test_pass():
u'test_fancy_items_regression test_pass'
u' test_fancy_items_regression.py',
]


def test_global_properties(testdir):
path = testdir.tmpdir.join("test_global_properties.xml")
log = LogXML(str(path), None)
from _pytest.runner import BaseReport

class Report(BaseReport):
sections = []
nodeid = "test_node_id"

log.pytest_sessionstart()
log.add_global_property('foo', 1)
log.add_global_property('bar', 2)
log.pytest_sessionfinish()

dom = minidom.parse(str(path))

properties = dom.getElementsByTagName('properties')

assert (properties.length == 1), "There must be one <properties> node"

property_list = dom.getElementsByTagName('property')

assert (property_list.length == 2), "There most be only 2 property nodes"

expected = {'foo': '1', 'bar': '2'}
actual = {}

for p in property_list:
k = str(p.getAttribute('name'))
v = str(p.getAttribute('value'))
actual[k] = v

assert actual == expected

0 comments on commit ceacc12

Please sign in to comment.