diff --git a/_pytest/junitxml.py b/_pytest/junitxml.py index 3d436d776..fa8b1c5ee 100644 --- a/_pytest/junitxml.py +++ b/_pytest/junitxml.py @@ -71,13 +71,12 @@ class LogXML(object): self.test_logs = [] self.passed = self.skipped = 0 self.failed = self.errors = 0 - self._durations = {} def _opentestcase(self, report): names = report.nodeid.split("::") names[0] = names[0].replace("/", '.') names = tuple(names) - d = {'time': self._durations.pop(report.nodeid, "0")} + d = {'time': getattr(report, 'duration', 0)} names = [x.replace(".py", "") for x in names if x != "()"] classnames = names[:-1] if self.prefix: @@ -176,13 +175,6 @@ class LogXML(object): elif report.skipped: self.append_skipped(report) - def pytest_runtest_call(self, item, __multicall__): - start = time.time() - try: - return __multicall__.execute() - finally: - self._durations[item.nodeid] = time.time() - start - def pytest_collectreport(self, report): if not report.passed: if report.failed: diff --git a/_pytest/runner.py b/_pytest/runner.py index be34bb72c..fa56e1459 100644 --- a/_pytest/runner.py +++ b/_pytest/runner.py @@ -1,6 +1,6 @@ """ basic collect and runtest protocol implementations """ -import py, sys +import py, sys, time from py._code.code import TerminalRepr def pytest_namespace(): @@ -95,12 +95,16 @@ class CallInfo: #: context of invocation: one of "setup", "call", #: "teardown", "memocollect" self.when = when + self.start = time.time() try: - self.result = func() - except KeyboardInterrupt: - raise - except: - self.excinfo = py.code.ExceptionInfo() + try: + self.result = func() + except KeyboardInterrupt: + raise + except: + self.excinfo = py.code.ExceptionInfo() + finally: + self.stop = time.time() def __repr__(self): if self.excinfo: @@ -139,6 +143,7 @@ class BaseReport(object): def pytest_runtest_makereport(item, call): when = call.when + duration = call.stop-call.start keywords = dict([(x,1) for x in item.keywords]) excinfo = call.excinfo if not call.excinfo: @@ -160,14 +165,15 @@ def pytest_runtest_makereport(item, call): else: # exception in setup or teardown longrepr = item._repr_failure_py(excinfo) return TestReport(item.nodeid, item.location, - keywords, outcome, longrepr, when) + keywords, outcome, longrepr, when, + duration=duration) class TestReport(BaseReport): """ Basic test report object (also used for setup and teardown calls if they fail). """ def __init__(self, nodeid, location, - keywords, outcome, longrepr, when, sections=()): + keywords, outcome, longrepr, when, sections=(), duration=0): #: normalized collection node id self.nodeid = nodeid @@ -193,6 +199,9 @@ class TestReport(BaseReport): #: marshallable self.sections = list(sections) + #: time it took to run just the test + self.duration = duration + def __repr__(self): return "" % ( self.nodeid, self.when, self.outcome)