introduce an option that avoids discovery of classes other than unittest.TestCase in modules
importing unittest.
This commit is contained in:
parent
707775dcfa
commit
d0ac4135a2
|
@ -403,7 +403,11 @@ def main(args=None, plugins=None):
|
|||
if args is None:
|
||||
args = sys.argv[1:]
|
||||
elif not isinstance(args, (tuple, list)):
|
||||
args = py.std.shlex.split(str(args))
|
||||
if isinstance(args, py.path.local):
|
||||
args = str(args)
|
||||
if not isinstance(args, str):
|
||||
raise ValueError("not a string or argument list: %r" % (args,))
|
||||
args = py.std.shlex.split(args)
|
||||
if _preinit:
|
||||
_pluginmanager = _preinit.pop(0)
|
||||
else: # subsequent calls to main will create a fresh instance
|
||||
|
|
|
@ -3,6 +3,7 @@ support for presented detailed information in failing assertions.
|
|||
"""
|
||||
import py
|
||||
import sys
|
||||
from pytest.plugin.monkeypatch import monkeypatch
|
||||
|
||||
def pytest_addoption(parser):
|
||||
group = parser.getgroup("debugconfig")
|
||||
|
@ -15,25 +16,21 @@ def pytest_configure(config):
|
|||
# py._code._assertionnew to detect this plugin was loaded and in
|
||||
# turn call the hooks defined here as part of the
|
||||
# DebugInterpreter.
|
||||
config._monkeypatch = m = monkeypatch()
|
||||
if not config.getvalue("noassert") and not config.getvalue("nomagic"):
|
||||
warn_about_missing_assertion()
|
||||
config._oldassertion = py.builtin.builtins.AssertionError
|
||||
config._oldbinrepr = py.code._reprcompare
|
||||
py.builtin.builtins.AssertionError = py.code._AssertionError
|
||||
def callbinrepr(op, left, right):
|
||||
hook_result = config.hook.pytest_assertrepr_compare(
|
||||
config=config, op=op, left=left, right=right)
|
||||
for new_expl in hook_result:
|
||||
if new_expl:
|
||||
return '\n~'.join(new_expl)
|
||||
py.code._reprcompare = callbinrepr
|
||||
m.setattr(py.builtin.builtins,
|
||||
'AssertionError', py.code._AssertionError)
|
||||
m.setattr(py.code, '_reprcompare', callbinrepr)
|
||||
|
||||
def pytest_unconfigure(config):
|
||||
if hasattr(config, '_oldassertion'):
|
||||
py.builtin.builtins.AssertionError = config._oldassertion
|
||||
py.code._reprcompare = config._oldbinrepr
|
||||
del config._oldassertion
|
||||
del config._oldbinrepr
|
||||
config._monkeypatch.undo()
|
||||
|
||||
def warn_about_missing_assertion():
|
||||
try:
|
||||
|
|
|
@ -59,6 +59,8 @@ def pytest_pycollect_makeitem(__multicall__, collector, name, obj):
|
|||
if res is not None:
|
||||
return res
|
||||
if collector._istestclasscandidate(name, obj):
|
||||
if hasattr(collector.obj, 'unittest'):
|
||||
return # we assume it's a mixin class for a TestCase derived one
|
||||
return Class(name, parent=collector)
|
||||
elif collector.funcnamefilter(name) and hasattr(obj, '__call__'):
|
||||
if is_generator(obj):
|
||||
|
@ -124,6 +126,7 @@ class PyobjMixin(object):
|
|||
return self._fslineno
|
||||
|
||||
def reportinfo(self):
|
||||
# XXX caching?
|
||||
obj = self.obj
|
||||
if hasattr(obj, 'compat_co_firstlineno'):
|
||||
# nose compatibility
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
""" support discovery and running of traditional "unittest.py" style tests. """
|
||||
""" discovery and running of std-library "unittest" style tests. """
|
||||
import py
|
||||
import sys
|
||||
|
||||
def pytest_pycollect_makeitem(collector, name, obj):
|
||||
if 'unittest' not in sys.modules:
|
||||
return # nobody derived unittest.TestCase
|
||||
unittest = sys.modules.get('unittest')
|
||||
if unittest is None:
|
||||
return # nobody can have derived unittest.TestCase
|
||||
try:
|
||||
isunit = issubclass(obj, py.std.unittest.TestCase)
|
||||
isunit = issubclass(obj, unittest.TestCase)
|
||||
except KeyboardInterrupt:
|
||||
raise
|
||||
except Exception:
|
||||
|
|
|
@ -294,6 +294,7 @@ class TestInvocationVariants:
|
|||
assert not retcode
|
||||
out, err = capsys.readouterr()
|
||||
assert "--help" in out
|
||||
pytest.raises(ValueError, lambda: pytest.main(retcode))
|
||||
|
||||
def test_invoke_with_path(self, testdir, capsys):
|
||||
retcode = testdir.pytestmain(testdir.tmpdir)
|
||||
|
@ -330,3 +331,18 @@ class TestInvocationVariants:
|
|||
result.stderr.fnmatch_lines([
|
||||
"ERROR*file*or*package*not*found*",
|
||||
])
|
||||
|
||||
|
||||
def test_noclass_discovery_if_not_testcase(self, testdir):
|
||||
testpath = testdir.makepyfile("""
|
||||
import unittest
|
||||
import py
|
||||
class TestHello(object):
|
||||
def test_hello(self):
|
||||
assert self.attr
|
||||
|
||||
class RealTest(TestHello, unittest.TestCase):
|
||||
attr = 42
|
||||
""")
|
||||
reprec = testdir.inline_run(testpath)
|
||||
reprec.assertoutcome(passed=1)
|
||||
|
|
|
@ -161,6 +161,15 @@ def test_functional(testdir):
|
|||
result = testdir.runpytest("--no-assert")
|
||||
assert "3 == 4" not in result.stdout.str()
|
||||
|
||||
def test_AssertionErrorIdentity(testdir):
|
||||
testdir.makepyfile("""
|
||||
def test_hello():
|
||||
import exceptions
|
||||
assert AssertionError is exceptions.AssertionError
|
||||
""")
|
||||
result = testdir.runpytest()
|
||||
result.stdout.fnmatch_lines(["*1 passed*"])
|
||||
|
||||
def test_triple_quoted_string_issue113(testdir):
|
||||
testdir.makepyfile("""
|
||||
def test_hello():
|
||||
|
|
Loading…
Reference in New Issue