Merge pull request #4285 from kchmck/fix-4046
Fix problems with running tests in package `__init__` files (#4046)
This commit is contained in:
commit
21725e9304
|
@ -0,0 +1 @@
|
||||||
|
Fix problems with running tests in package ``__init__.py`` files.
|
|
@ -281,15 +281,6 @@ def pytest_ignore_collect(path, config):
|
||||||
if _in_venv(path) and not allow_in_venv:
|
if _in_venv(path) and not allow_in_venv:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
# Skip duplicate paths.
|
|
||||||
keepduplicates = config.getoption("keepduplicates")
|
|
||||||
duplicate_paths = config.pluginmanager._duplicatepaths
|
|
||||||
if not keepduplicates:
|
|
||||||
if path in duplicate_paths:
|
|
||||||
return True
|
|
||||||
else:
|
|
||||||
duplicate_paths.add(path)
|
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
@ -551,7 +542,15 @@ class Session(nodes.FSCollector):
|
||||||
col = root._collectfile(argpath)
|
col = root._collectfile(argpath)
|
||||||
if col:
|
if col:
|
||||||
self._node_cache[argpath] = col
|
self._node_cache[argpath] = col
|
||||||
for y in self.matchnodes(col, names):
|
m = self.matchnodes(col, names)
|
||||||
|
# If __init__.py was the only file requested, then the matched node will be
|
||||||
|
# the corresponding Package, and the first yielded item will be the __init__
|
||||||
|
# Module itself, so just use that. If this special case isn't taken, then all
|
||||||
|
# the files in the package will be yielded.
|
||||||
|
if argpath.basename == "__init__.py":
|
||||||
|
yield next(m[0].collect())
|
||||||
|
return
|
||||||
|
for y in m:
|
||||||
yield y
|
yield y
|
||||||
|
|
||||||
def _collectfile(self, path):
|
def _collectfile(self, path):
|
||||||
|
@ -559,6 +558,16 @@ class Session(nodes.FSCollector):
|
||||||
if not self.isinitpath(path):
|
if not self.isinitpath(path):
|
||||||
if ihook.pytest_ignore_collect(path=path, config=self.config):
|
if ihook.pytest_ignore_collect(path=path, config=self.config):
|
||||||
return ()
|
return ()
|
||||||
|
|
||||||
|
# Skip duplicate paths.
|
||||||
|
keepduplicates = self.config.getoption("keepduplicates")
|
||||||
|
if not keepduplicates:
|
||||||
|
duplicate_paths = self.config.pluginmanager._duplicatepaths
|
||||||
|
if path in duplicate_paths:
|
||||||
|
return ()
|
||||||
|
else:
|
||||||
|
duplicate_paths.add(path)
|
||||||
|
|
||||||
return ihook.pytest_collect_file(path=path, parent=self)
|
return ihook.pytest_collect_file(path=path, parent=self)
|
||||||
|
|
||||||
def _recurse(self, path):
|
def _recurse(self, path):
|
||||||
|
|
|
@ -553,15 +553,6 @@ class Package(Module):
|
||||||
return path in self.session._initialpaths
|
return path in self.session._initialpaths
|
||||||
|
|
||||||
def collect(self):
|
def collect(self):
|
||||||
# XXX: HACK!
|
|
||||||
# Before starting to collect any files from this package we need
|
|
||||||
# to cleanup the duplicate paths added by the session's collect().
|
|
||||||
# Proper fix is to not track these as duplicates in the first place.
|
|
||||||
for path in list(self.session.config.pluginmanager._duplicatepaths):
|
|
||||||
# if path.parts()[:len(self.fspath.dirpath().parts())] == self.fspath.dirpath().parts():
|
|
||||||
if path.dirname.startswith(self.name):
|
|
||||||
self.session.config.pluginmanager._duplicatepaths.remove(path)
|
|
||||||
|
|
||||||
this_path = self.fspath.dirpath()
|
this_path = self.fspath.dirpath()
|
||||||
init_module = this_path.join("__init__.py")
|
init_module = this_path.join("__init__.py")
|
||||||
if init_module.check(file=1) and path_matches_patterns(
|
if init_module.check(file=1) and path_matches_patterns(
|
||||||
|
|
|
@ -957,6 +957,21 @@ def test_collect_init_tests(testdir):
|
||||||
"*<Function 'test_foo'>",
|
"*<Function 'test_foo'>",
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
result = testdir.runpytest("./tests", "--collect-only")
|
||||||
|
result.stdout.fnmatch_lines(
|
||||||
|
[
|
||||||
|
"*<Module '__init__.py'>",
|
||||||
|
"*<Function 'test_init'>",
|
||||||
|
"*<Module 'test_foo.py'>",
|
||||||
|
"*<Function 'test_foo'>",
|
||||||
|
]
|
||||||
|
)
|
||||||
|
result = testdir.runpytest("./tests/test_foo.py", "--collect-only")
|
||||||
|
result.stdout.fnmatch_lines(["*<Module 'test_foo.py'>", "*<Function 'test_foo'>"])
|
||||||
|
assert "test_init" not in result.stdout.str()
|
||||||
|
result = testdir.runpytest("./tests/__init__.py", "--collect-only")
|
||||||
|
result.stdout.fnmatch_lines(["*<Module '__init__.py'>", "*<Function 'test_init'>"])
|
||||||
|
assert "test_foo" not in result.stdout.str()
|
||||||
|
|
||||||
|
|
||||||
def test_collect_invalid_signature_message(testdir):
|
def test_collect_invalid_signature_message(testdir):
|
||||||
|
|
|
@ -219,7 +219,7 @@ class TestNewSession(SessionTests):
|
||||||
started = reprec.getcalls("pytest_collectstart")
|
started = reprec.getcalls("pytest_collectstart")
|
||||||
finished = reprec.getreports("pytest_collectreport")
|
finished = reprec.getreports("pytest_collectreport")
|
||||||
assert len(started) == len(finished)
|
assert len(started) == len(finished)
|
||||||
assert len(started) == 7 # XXX extra TopCollector
|
assert len(started) == 8
|
||||||
colfail = [x for x in finished if x.failed]
|
colfail = [x for x in finished if x.failed]
|
||||||
assert len(colfail) == 1
|
assert len(colfail) == 1
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue