warn if instances are callable and have a test name

This commit is contained in:
holger krekel 2014-03-11 22:10:18 +01:00
parent 1b387bea62
commit 24db492f53
3 changed files with 32 additions and 16 deletions

View File

@ -11,7 +11,8 @@ cutdir = py.path.local(_pytest.__file__).dirpath()
NoneType = type(None) NoneType = type(None)
NOTSET = object() NOTSET = object()
isfunction = inspect.isfunction
isclass = inspect.isclass
callable = py.builtin.callable callable = py.builtin.callable
def getfslineno(obj): def getfslineno(obj):
@ -44,7 +45,7 @@ class FixtureFunctionMarker:
self.ids = ids self.ids = ids
def __call__(self, function): def __call__(self, function):
if inspect.isclass(function): if isclass(function):
raise ValueError( raise ValueError(
"class fixtures not supported (may be in the future)") "class fixtures not supported (may be in the future)")
function._pytestfixturefunction = self function._pytestfixturefunction = self
@ -213,14 +214,19 @@ def pytest_pycollect_makeitem(__multicall__, collector, name, obj):
res = __multicall__.execute() res = __multicall__.execute()
if res is not None: if res is not None:
return res return res
if inspect.isclass(obj): if isclass(obj):
#if hasattr(collector.obj, 'unittest'): #if hasattr(collector.obj, 'unittest'):
# return # we assume it's a mixin class for a TestCase derived one # return # we assume it's a mixin class for a TestCase derived one
if collector.classnamefilter(name): if collector.classnamefilter(name):
Class = collector._getcustomclass("Class") Class = collector._getcustomclass("Class")
return Class(name, parent=collector) return Class(name, parent=collector)
elif collector.funcnamefilter(name) and hasattr(obj, '__call__') and \ elif collector.funcnamefilter(name) and hasattr(obj, "__call__") and \
getfixturemarker(obj) is None: getfixturemarker(obj) is None:
if not isfunction(obj):
collector.warn(code="C2", message=
"cannot collect %r because it is not a function."
% name, )
return
if is_generator(obj): if is_generator(obj):
return Generator(name, parent=collector) return Generator(name, parent=collector)
else: else:
@ -498,10 +504,9 @@ class Class(PyCollector):
""" Collector for test methods. """ """ Collector for test methods. """
def collect(self): def collect(self):
if hasinit(self.obj): if hasinit(self.obj):
pytest.skip("class %s.%s with __init__ won't get collected" % ( self.warn("C1", "cannot collect test class %r because it has a "
self.obj.__module__, "__init__ constructor" % self.obj.__name__)
self.obj.__name__, return []
))
return [self._getcustomclass("Instance")(name="()", parent=self)] return [self._getcustomclass("Instance")(name="()", parent=self)]
def setup(self): def setup(self):

View File

@ -15,7 +15,7 @@ def pytest_addoption(parser):
group._addoption('-r', group._addoption('-r',
action="store", dest="reportchars", default=None, metavar="chars", action="store", dest="reportchars", default=None, metavar="chars",
help="show extra test summary info as specified by chars (f)ailed, " help="show extra test summary info as specified by chars (f)ailed, "
"(E)error, (s)skipped, (x)failed, (X)passed.") "(E)error, (s)skipped, (x)failed, (X)passed (w)warnings.")
group._addoption('-l', '--showlocals', group._addoption('-l', '--showlocals',
action="store_true", dest="showlocals", default=False, action="store_true", dest="showlocals", default=False,
help="show locals in tracebacks (disabled by default).") help="show locals in tracebacks (disabled by default).")

View File

@ -33,8 +33,8 @@ class TestModule:
pytest.raises(ImportError, lambda: modcol.obj) pytest.raises(ImportError, lambda: modcol.obj)
class TestClass: class TestClass:
def test_class_with_init_skip_collect(self, testdir): def test_class_with_init_warning(self, testdir):
modcol = testdir.getmodulecol(""" testdir.makepyfile("""
class TestClass1: class TestClass1:
def __init__(self): def __init__(self):
pass pass
@ -42,11 +42,11 @@ class TestClass:
def __init__(self): def __init__(self):
pass pass
""") """)
l = modcol.collect() result = testdir.runpytest("-rw")
assert len(l) == 2 result.stdout.fnmatch_lines("""
WC1*test_class_with_init_warning.py*__init__*
for classcol in l: *2 warnings*
pytest.raises(pytest.skip.Exception, classcol.collect) """)
def test_class_subclassobject(self, testdir): def test_class_subclassobject(self, testdir):
testdir.getmodulecol(""" testdir.getmodulecol("""
@ -276,6 +276,17 @@ class TestFunction:
assert isinstance(modcol, pytest.Module) assert isinstance(modcol, pytest.Module)
assert hasattr(modcol.obj, 'test_func') assert hasattr(modcol.obj, 'test_func')
def test_function_as_object_instance_ignored(self, testdir):
item = testdir.makepyfile("""
class A:
def __call__(self, tmpdir):
0/0
test_a = A()
""")
reprec = testdir.inline_run()
reprec.assertoutcome()
def test_function_equality(self, testdir, tmpdir): def test_function_equality(self, testdir, tmpdir):
from _pytest.python import FixtureManager from _pytest.python import FixtureManager
config = testdir.parseconfigure() config = testdir.parseconfigure()