collection: Prevent non-function callables from being collected
Fixes issue 331 previously to this change the collection code would issue a warning for when ever it encountered a variable that looked like a test but wasn't a function saying that it wouldn't collect it because it wasn't a function. This fixes the logic so that if that warning is issued it really isn't collected. However previously special cases existed to support tests that were created using functools.wraps and functools.partial. So the condition for issuing that warning has been updated to take that in to account Also try the old way of detecting functions just for proper integration with mock.path in python 2.7 the get_real_func returned the unbound method
This commit is contained in:
parent
0c21533cc5
commit
a3bda59a30
1
AUTHORS
1
AUTHORS
|
@ -51,6 +51,7 @@ Marc Schlaich
|
|||
Mark Abramowitz
|
||||
Markus Unterwaditzer
|
||||
Martijn Faassen
|
||||
Michael Birtwell
|
||||
Michael Droettboom
|
||||
Nicolas Delaby
|
||||
Pieter Mulder
|
||||
|
|
|
@ -4,6 +4,9 @@
|
|||
- fix #1035: collecting tests if test module level obj has __getattr__().
|
||||
Thanks Suor for the report and Bruno Oliveira / Tom Viner for the PR.
|
||||
|
||||
- fix #331: don't collect tests if their failure cannot be reported correctly
|
||||
e.g. they are a callable instance of a class.
|
||||
|
||||
2.8.2
|
||||
-----
|
||||
|
||||
|
|
|
@ -312,11 +312,14 @@ def pytest_pycollect_makeitem(collector, name, obj):
|
|||
elif collector.istestfunction(obj, name):
|
||||
# mock seems to store unbound methods (issue473), normalize it
|
||||
obj = getattr(obj, "__func__", obj)
|
||||
if not isfunction(obj):
|
||||
# We need to try and unwrap the function if it's a functools.partial
|
||||
# or a funtools.wrapped.
|
||||
# We musn't if it's been wrapped with mock.patch (python 2 only)
|
||||
if not (isfunction(obj) or isfunction(get_real_func(obj))):
|
||||
collector.warn(code="C2", message=
|
||||
"cannot collect %r because it is not a function."
|
||||
% name, )
|
||||
if getattr(obj, "__test__", True):
|
||||
elif getattr(obj, "__test__", True):
|
||||
if is_generator(obj):
|
||||
res = Generator(name, parent=collector)
|
||||
else:
|
||||
|
|
|
@ -1013,3 +1013,27 @@ def test_collect_functools_partial(testdir):
|
|||
""")
|
||||
result = testdir.inline_run()
|
||||
result.assertoutcome(passed=6, failed=2)
|
||||
|
||||
|
||||
def test_dont_collect_non_function_callable(testdir):
|
||||
"""Test for issue https://github.com/pytest-dev/pytest/issues/331
|
||||
|
||||
In this case an INTERNALERROR occurred trying to report the failure of
|
||||
a test like this one because py test failed to get the source lines.
|
||||
"""
|
||||
testdir.makepyfile("""
|
||||
class Oh(object):
|
||||
def __call__(self):
|
||||
pass
|
||||
|
||||
test_a = Oh()
|
||||
|
||||
def test_real():
|
||||
pass
|
||||
""")
|
||||
result = testdir.runpytest('-rw')
|
||||
result.stdout.fnmatch_lines([
|
||||
'*collected 1 item*',
|
||||
'WC2 *',
|
||||
'*1 passed, 1 pytest-warnings in *',
|
||||
])
|
||||
|
|
Loading…
Reference in New Issue