fixup nose/pytest plugins
This commit is contained in:
parent
c9ab421398
commit
efe03400d8
|
@ -4,8 +4,8 @@ from __future__ import absolute_import, division, print_function
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
import py
|
import py
|
||||||
import pytest
|
from _pytest import unittest, runner, python
|
||||||
from _pytest import unittest
|
from _pytest.config import hookimpl
|
||||||
|
|
||||||
|
|
||||||
def get_skip_exceptions():
|
def get_skip_exceptions():
|
||||||
|
@ -20,19 +20,19 @@ def get_skip_exceptions():
|
||||||
def pytest_runtest_makereport(item, call):
|
def pytest_runtest_makereport(item, call):
|
||||||
if call.excinfo and call.excinfo.errisinstance(get_skip_exceptions()):
|
if call.excinfo and call.excinfo.errisinstance(get_skip_exceptions()):
|
||||||
# let's substitute the excinfo with a pytest.skip one
|
# let's substitute the excinfo with a pytest.skip one
|
||||||
call2 = call.__class__(lambda:
|
call2 = call.__class__(
|
||||||
pytest.skip(str(call.excinfo.value)), call.when)
|
lambda: runner.skip(str(call.excinfo.value)), call.when)
|
||||||
call.excinfo = call2.excinfo
|
call.excinfo = call2.excinfo
|
||||||
|
|
||||||
|
|
||||||
@pytest.hookimpl(trylast=True)
|
@hookimpl(trylast=True)
|
||||||
def pytest_runtest_setup(item):
|
def pytest_runtest_setup(item):
|
||||||
if is_potential_nosetest(item):
|
if is_potential_nosetest(item):
|
||||||
if isinstance(item.parent, pytest.Generator):
|
if isinstance(item.parent, python.Generator):
|
||||||
gen = item.parent
|
gen = item.parent
|
||||||
if not hasattr(gen, '_nosegensetup'):
|
if not hasattr(gen, '_nosegensetup'):
|
||||||
call_optional(gen.obj, 'setup')
|
call_optional(gen.obj, 'setup')
|
||||||
if isinstance(gen.parent, pytest.Instance):
|
if isinstance(gen.parent, python.Instance):
|
||||||
call_optional(gen.parent.obj, 'setup')
|
call_optional(gen.parent.obj, 'setup')
|
||||||
gen._nosegensetup = True
|
gen._nosegensetup = True
|
||||||
if not call_optional(item.obj, 'setup'):
|
if not call_optional(item.obj, 'setup'):
|
||||||
|
@ -51,14 +51,14 @@ def teardown_nose(item):
|
||||||
|
|
||||||
|
|
||||||
def pytest_make_collect_report(collector):
|
def pytest_make_collect_report(collector):
|
||||||
if isinstance(collector, pytest.Generator):
|
if isinstance(collector, python.Generator):
|
||||||
call_optional(collector.obj, 'setup')
|
call_optional(collector.obj, 'setup')
|
||||||
|
|
||||||
|
|
||||||
def is_potential_nosetest(item):
|
def is_potential_nosetest(item):
|
||||||
# extra check needed since we do not do nose style setup/teardown
|
# extra check needed since we do not do nose style setup/teardown
|
||||||
# on direct unittest style classes
|
# on direct unittest style classes
|
||||||
return isinstance(item, pytest.Function) and \
|
return isinstance(item, python.Function) and \
|
||||||
not isinstance(item, unittest.TestCaseFunction)
|
not isinstance(item, unittest.TestCaseFunction)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -4,11 +4,12 @@ from __future__ import absolute_import, division, print_function
|
||||||
import sys
|
import sys
|
||||||
import traceback
|
import traceback
|
||||||
|
|
||||||
import pytest
|
|
||||||
# for transferring markers
|
# for transferring markers
|
||||||
import _pytest._code
|
import _pytest._code
|
||||||
from _pytest.python import transfer_markers
|
from _pytest.config import hookimpl
|
||||||
from _pytest.skipping import MarkEvaluator
|
from _pytest.runner import fail, skip
|
||||||
|
from _pytest.python import transfer_markers, Class, Module, Function
|
||||||
|
from _pytest.skipping import MarkEvaluator, xfail
|
||||||
|
|
||||||
|
|
||||||
def pytest_pycollect_makeitem(collector, name, obj):
|
def pytest_pycollect_makeitem(collector, name, obj):
|
||||||
|
@ -22,11 +23,11 @@ def pytest_pycollect_makeitem(collector, name, obj):
|
||||||
return UnitTestCase(name, parent=collector)
|
return UnitTestCase(name, parent=collector)
|
||||||
|
|
||||||
|
|
||||||
class UnitTestCase(pytest.Class):
|
class UnitTestCase(Class):
|
||||||
# marker for fixturemanger.getfixtureinfo()
|
# marker for fixturemanger.getfixtureinfo()
|
||||||
# to declare that our children do not support funcargs
|
# to declare that our children do not support funcargs
|
||||||
nofuncargs = True
|
nofuncargs = True
|
||||||
|
|
||||||
def setup(self):
|
def setup(self):
|
||||||
cls = self.obj
|
cls = self.obj
|
||||||
if getattr(cls, '__unittest_skip__', False):
|
if getattr(cls, '__unittest_skip__', False):
|
||||||
|
@ -46,7 +47,7 @@ class UnitTestCase(pytest.Class):
|
||||||
return
|
return
|
||||||
self.session._fixturemanager.parsefactories(self, unittest=True)
|
self.session._fixturemanager.parsefactories(self, unittest=True)
|
||||||
loader = TestLoader()
|
loader = TestLoader()
|
||||||
module = self.getparent(pytest.Module).obj
|
module = self.getparent(Module).obj
|
||||||
foundsomething = False
|
foundsomething = False
|
||||||
for name in loader.getTestCaseNames(self.obj):
|
for name in loader.getTestCaseNames(self.obj):
|
||||||
x = getattr(self.obj, name)
|
x = getattr(self.obj, name)
|
||||||
|
@ -65,7 +66,7 @@ class UnitTestCase(pytest.Class):
|
||||||
yield TestCaseFunction('runTest', parent=self)
|
yield TestCaseFunction('runTest', parent=self)
|
||||||
|
|
||||||
|
|
||||||
class TestCaseFunction(pytest.Function):
|
class TestCaseFunction(Function):
|
||||||
_excinfo = None
|
_excinfo = None
|
||||||
|
|
||||||
def setup(self):
|
def setup(self):
|
||||||
|
@ -110,36 +111,37 @@ class TestCaseFunction(pytest.Function):
|
||||||
try:
|
try:
|
||||||
l = traceback.format_exception(*rawexcinfo)
|
l = traceback.format_exception(*rawexcinfo)
|
||||||
l.insert(0, "NOTE: Incompatible Exception Representation, "
|
l.insert(0, "NOTE: Incompatible Exception Representation, "
|
||||||
"displaying natively:\n\n")
|
"displaying natively:\n\n")
|
||||||
pytest.fail("".join(l), pytrace=False)
|
fail("".join(l), pytrace=False)
|
||||||
except (pytest.fail.Exception, KeyboardInterrupt):
|
except (fail.Exception, KeyboardInterrupt):
|
||||||
raise
|
raise
|
||||||
except:
|
except:
|
||||||
pytest.fail("ERROR: Unknown Incompatible Exception "
|
fail("ERROR: Unknown Incompatible Exception "
|
||||||
"representation:\n%r" %(rawexcinfo,), pytrace=False)
|
"representation:\n%r" % (rawexcinfo,), pytrace=False)
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
raise
|
raise
|
||||||
except pytest.fail.Exception:
|
except fail.Exception:
|
||||||
excinfo = _pytest._code.ExceptionInfo()
|
excinfo = _pytest._code.ExceptionInfo()
|
||||||
self.__dict__.setdefault('_excinfo', []).append(excinfo)
|
self.__dict__.setdefault('_excinfo', []).append(excinfo)
|
||||||
|
|
||||||
def addError(self, testcase, rawexcinfo):
|
def addError(self, testcase, rawexcinfo):
|
||||||
self._addexcinfo(rawexcinfo)
|
self._addexcinfo(rawexcinfo)
|
||||||
|
|
||||||
def addFailure(self, testcase, rawexcinfo):
|
def addFailure(self, testcase, rawexcinfo):
|
||||||
self._addexcinfo(rawexcinfo)
|
self._addexcinfo(rawexcinfo)
|
||||||
|
|
||||||
def addSkip(self, testcase, reason):
|
def addSkip(self, testcase, reason):
|
||||||
try:
|
try:
|
||||||
pytest.skip(reason)
|
skip(reason)
|
||||||
except pytest.skip.Exception:
|
except skip.Exception:
|
||||||
self._evalskip = MarkEvaluator(self, 'SkipTest')
|
self._evalskip = MarkEvaluator(self, 'SkipTest')
|
||||||
self._evalskip.result = True
|
self._evalskip.result = True
|
||||||
self._addexcinfo(sys.exc_info())
|
self._addexcinfo(sys.exc_info())
|
||||||
|
|
||||||
def addExpectedFailure(self, testcase, rawexcinfo, reason=""):
|
def addExpectedFailure(self, testcase, rawexcinfo, reason=""):
|
||||||
try:
|
try:
|
||||||
pytest.xfail(str(reason))
|
xfail(str(reason))
|
||||||
except pytest.xfail.Exception:
|
except xfail.Exception:
|
||||||
self._addexcinfo(sys.exc_info())
|
self._addexcinfo(sys.exc_info())
|
||||||
|
|
||||||
def addUnexpectedSuccess(self, testcase, reason=""):
|
def addUnexpectedSuccess(self, testcase, reason=""):
|
||||||
|
@ -179,13 +181,14 @@ class TestCaseFunction(pytest.Function):
|
||||||
self._testcase.debug()
|
self._testcase.debug()
|
||||||
|
|
||||||
def _prunetraceback(self, excinfo):
|
def _prunetraceback(self, excinfo):
|
||||||
pytest.Function._prunetraceback(self, excinfo)
|
Function._prunetraceback(self, excinfo)
|
||||||
traceback = excinfo.traceback.filter(
|
traceback = excinfo.traceback.filter(
|
||||||
lambda x:not x.frame.f_globals.get('__unittest'))
|
lambda x: not x.frame.f_globals.get('__unittest'))
|
||||||
if traceback:
|
if traceback:
|
||||||
excinfo.traceback = traceback
|
excinfo.traceback = traceback
|
||||||
|
|
||||||
@pytest.hookimpl(tryfirst=True)
|
|
||||||
|
@hookimpl(tryfirst=True)
|
||||||
def pytest_runtest_makereport(item, call):
|
def pytest_runtest_makereport(item, call):
|
||||||
if isinstance(item, TestCaseFunction):
|
if isinstance(item, TestCaseFunction):
|
||||||
if item._excinfo:
|
if item._excinfo:
|
||||||
|
@ -197,7 +200,8 @@ def pytest_runtest_makereport(item, call):
|
||||||
|
|
||||||
# twisted trial support
|
# twisted trial support
|
||||||
|
|
||||||
@pytest.hookimpl(hookwrapper=True)
|
|
||||||
|
@hookimpl(hookwrapper=True)
|
||||||
def pytest_runtest_protocol(item):
|
def pytest_runtest_protocol(item):
|
||||||
if isinstance(item, TestCaseFunction) and \
|
if isinstance(item, TestCaseFunction) and \
|
||||||
'twisted.trial.unittest' in sys.modules:
|
'twisted.trial.unittest' in sys.modules:
|
||||||
|
|
Loading…
Reference in New Issue