Skip to content

Commit

Permalink
Merge pull request pytest-dev#4529 from aparamon/jxmlunit-call-time
Browse files Browse the repository at this point in the history
Add --junittime=call option
  • Loading branch information
nicoddemus authored Dec 13, 2018
2 parents b390c66 + 5d79baf commit 26d202a
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 3 deletions.
1 change: 1 addition & 0 deletions AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ Anders Hovmöller
Andras Tim
Andrea Cimatoribus
Andreas Zeidler
Andrey Paramonov
Andrzej Ostrowski
Andy Freeland
Anthon van der Neut
Expand Down
2 changes: 2 additions & 0 deletions changelog/4483.feature.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Add ini parameter ``junit_time`` to optionally report test call
durations less setup and teardown times.
14 changes: 14 additions & 0 deletions doc/en/usage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,20 @@ To set the name of the root test suite xml item, you can configure the ``junit_s
[pytest]
junit_suite_name = my_suite
.. versionadded:: 4.0

JUnit XML specification seems to indicate that ``"time"`` attribute
should report total test execution times, including setup and teardown
(`1 <http://windyroad.com.au/dl/Open%20Source/JUnit.xsd>`_, `2
<https://www.ibm.com/support/knowledgecenter/en/SSQ2R2_14.1.0/com.ibm.rsar.analysis.codereview.cobol.doc/topics/cac_useresults_junit.html>`_).
It is the default pytest behavior. To report just call durations
instead, configure the ``junit_time`` option like this:

.. code-block:: ini
[pytest]
junit_time = call
.. _record_property example:

record_property
Expand Down
19 changes: 16 additions & 3 deletions src/_pytest/junitxml.py
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,9 @@ def pytest_addoption(parser):
"one of no|system-out|system-err",
default="no",
) # choices=['no', 'stdout', 'stderr'])
parser.addini(
"junit_time", "Duration time to report: one of total|call", default="total"
) # choices=['total', 'call'])


def pytest_configure(config):
Expand All @@ -334,6 +337,7 @@ def pytest_configure(config):
config.option.junitprefix,
config.getini("junit_suite_name"),
config.getini("junit_logging"),
config.getini("junit_time"),
)
config.pluginmanager.register(config._xml)

Expand Down Expand Up @@ -361,12 +365,20 @@ def mangle_test_address(address):


class LogXML(object):
def __init__(self, logfile, prefix, suite_name="pytest", logging="no"):
def __init__(
self,
logfile,
prefix,
suite_name="pytest",
logging="no",
report_duration="total",
):
logfile = os.path.expanduser(os.path.expandvars(logfile))
self.logfile = os.path.normpath(os.path.abspath(logfile))
self.prefix = prefix
self.suite_name = suite_name
self.logging = logging
self.report_duration = report_duration
self.stats = dict.fromkeys(["error", "passed", "failure", "skipped"], 0)
self.node_reporters = {} # nodeid -> _NodeReporter
self.node_reporters_ordered = []
Expand Down Expand Up @@ -500,8 +512,9 @@ def update_testcase_duration(self, report):
"""accumulates total duration for nodeid from given report and updates
the Junit.testcase with the new total if already created.
"""
reporter = self.node_reporter(report)
reporter.duration += getattr(report, "duration", 0.0)
if self.report_duration == "total" or report.when == self.report_duration:
reporter = self.node_reporter(report)
reporter.duration += getattr(report, "duration", 0.0)

def pytest_collectreport(self, report):
if not report.passed:
Expand Down
18 changes: 18 additions & 0 deletions testing/test_junitxml.py
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,24 @@ def test_sleep():
val = tnode["time"]
assert round(float(val), 2) >= 0.03

def test_call_time(self, testdir):
testdir.makepyfile(
"""
import time, pytest
def setup_module():
time.sleep(0.1)
def teardown_module():
time.sleep(0.1)
def test_sleep():
time.sleep(0.1)
"""
)
result, dom = runandparse(testdir, "-o", "junit_time=call")
node = dom.find_first_by_tag("testsuite")
tnode = node.find_first_by_tag("testcase")
val = tnode["time"]
assert 0.1 <= round(float(val), 2) < 0.2

def test_setup_error(self, testdir):
testdir.makepyfile(
"""
Expand Down

0 comments on commit 26d202a

Please sign in to comment.