diff --git a/py/test/plugin/pytest_default.py b/py/test/plugin/pytest_default.py index 209fa3527..235bc6c5c 100644 --- a/py/test/plugin/pytest_default.py +++ b/py/test/plugin/pytest_default.py @@ -114,6 +114,10 @@ class DefaultPlugin: from py.__.test.dsession.dsession import DSession config.setsessionclass(DSession) + def pytest_item_makereport(self, item, excinfo, when, outerr): + from py.__.test import event + return event.ItemTestReport(item, excinfo, when, outerr) + def test_implied_different_sessions(tmpdir): def x(*args): config = py.test.config._reparse([tmpdir] + list(args)) diff --git a/py/test/plugin/pytest_plugintester.py b/py/test/plugin/pytest_plugintester.py index eb3986dbb..0b9b432d2 100644 --- a/py/test/plugin/pytest_plugintester.py +++ b/py/test/plugin/pytest_plugintester.py @@ -60,6 +60,8 @@ class PluginTester(Support): if not hasattr(hook, 'func_code'): continue # XXX do some checks on attributes as well? method_args = getargs(method.func_code) + if '__call__' in method_args[0]: + method_args[0].remove('__call__') hookargs = getargs(hook.func_code) for arg, hookarg in zip(method_args[0], hookargs[0]): if arg != hookarg: @@ -119,6 +121,9 @@ class PytestPluginHooks: def pytest_pyfunc_call(self, pyfuncitem, args, kwargs): """ return True if we consumed/did the call to the python function item. """ + def pytest_item_makereport(self, item, excinfo, when, outerr): + """ return ItemTestReport event for the given test outcome. """ + # collection hooks def pytest_collect_file(self, path, parent): """ return Collection node or None. """ @@ -134,6 +139,11 @@ class PytestPluginHooks: def pytest_pymodule_makeitem(self, modcol, name, obj): """ return custom item/collector for a python object in a module, or None. """ + + # from pytest_terminal plugin + def pytest_report_teststatus(self, event): + """ return shortletter and verbose word. """ + # from pytest_terminal plugin def pytest_report_teststatus(self, event): """ return shortletter and verbose word. """ diff --git a/py/test/plugin/pytest_xfail.py b/py/test/plugin/pytest_xfail.py index 87fe0d716..208d2e31c 100644 --- a/py/test/plugin/pytest_xfail.py +++ b/py/test/plugin/pytest_xfail.py @@ -9,12 +9,25 @@ import py class XfailPlugin(object): """ mark and report specially about "expected to fail" tests. """ + + def pytest_item_makereport(self, __call__, item, excinfo, when, outerr): + if hasattr(item, 'obj') and hasattr(item.obj, 'func_dict'): + if 'xfail' in item.obj.func_dict: + res = __call__.execute(firstresult=True) + if excinfo: + res.skipped = True + res.failed = res.passed = False + else: + res.skipped = res.passed = False + res.failed = True + return res + def pytest_report_teststatus(self, event): """ return shortletter and verbose word. """ if 'xfail' in event.keywords: - if event.failed: + if event.skipped: return "xfailed", "x", "xfail" - else: + elif event.failed: return "xpassed", "P", "xpass" # a hook implemented called by the terminalreporter instance/plugin @@ -22,7 +35,7 @@ class XfailPlugin(object): tr = terminalreporter xfailed = tr.stats.get("xfailed") if xfailed: - tr.write_sep("_", "EXPECTED XFAILURES") + tr.write_sep("_", "expected failures") for event in xfailed: entry = event.longrepr.reprcrash key = entry.path, entry.lineno, entry.message @@ -33,7 +46,7 @@ class XfailPlugin(object): xpassed = terminalreporter.stats.get("xpassed") if xpassed: - tr.write_sep("_", "UNEXPECTEDLY PASSING") + tr.write_sep("_", "UNEXPECTEDLY PASSING TESTS") for event in xpassed: tr._tw.line("%s: xpassed" %(event.colitem,)) @@ -54,10 +67,16 @@ def test_xfail(plugintester, linecomp): @py.test.mark.xfail def test_this(): assert 0 + + @py.test.mark.xfail + def test_that(): + assert 1 """) result = testdir.runpytest(p) extra = result.stdout.fnmatch_lines([ - "*XFAILURES*", + "*expected failures*", "*test_one.test_this*test_one.py:5*", + "*UNEXPECTEDLY PASSING*", + "*test_that*", ]) assert result.ret == 1 diff --git a/py/test/runner.py b/py/test/runner.py index e1c20c01e..cf01c012f 100644 --- a/py/test/runner.py +++ b/py/test/runner.py @@ -59,7 +59,9 @@ class ItemRunner(RobustRun): #self.colitem.config.pytestplugins.post_execute(self.colitem) def makereport(self, res, when, excinfo, outerr): - testrep = event.ItemTestReport(self.colitem, excinfo, when, outerr) + testrep = self.colitem._config.pytestplugins.call_firstresult( + "pytest_item_makereport", item=self.colitem, + excinfo=excinfo, when=when, outerr=outerr) if self.pdb and testrep.failed: tw = py.io.TerminalWriter() testrep.toterminal(tw)