Skip to content

Commit

Permalink
Merge pull request #3802 from jonozzz/fix-3768
Browse files Browse the repository at this point in the history
Fix test collection from packages mixed with directories. #3768 and #3789
  • Loading branch information
nicoddemus committed Aug 16, 2018
2 parents ca1bb9a + abae60c commit 64faa41
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 15 deletions.
1 change: 1 addition & 0 deletions changelog/3768.bugfix.rst
@@ -0,0 +1 @@
Fix test collection from packages mixed with normal directories.
1 change: 1 addition & 0 deletions changelog/3789.bugfix.rst
@@ -0,0 +1 @@
Fix test collection from packages mixed with normal directories.
25 changes: 10 additions & 15 deletions src/_pytest/python.py
Expand Up @@ -216,18 +216,6 @@ def pytest_pycollect_makemodule(path, parent):
return Module(path, parent)


def pytest_ignore_collect(path, config):
# Skip duplicate packages.
keepduplicates = config.getoption("keepduplicates")
if keepduplicates:
duplicate_paths = config.pluginmanager._duplicatepaths
if path.basename == "__init__.py":
if path in duplicate_paths:
return True
else:
duplicate_paths.add(path)


@hookimpl(hookwrapper=True)
def pytest_pycollect_makeitem(collector, name, obj):
outcome = yield
Expand Down Expand Up @@ -554,9 +542,7 @@ def __init__(self, fspath, parent=None, config=None, session=None, nodeid=None):
self.name = fspath.dirname
self.trace = session.trace
self._norecursepatterns = session._norecursepatterns
for path in list(session.config.pluginmanager._duplicatepaths):
if path.dirname == fspath.dirname and path != fspath:
session.config.pluginmanager._duplicatepaths.remove(path)
self.fspath = fspath

def _recurse(self, path):
ihook = self.gethookproxy(path.dirpath())
Expand Down Expand Up @@ -594,6 +580,15 @@ def isinitpath(self, path):
return path in self.session._initialpaths

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()
pkg_prefix = None
for path in this_path.visit(rec=self._recurse, bf=True, sort=True):
Expand Down
40 changes: 40 additions & 0 deletions testing/python/collect.py
Expand Up @@ -1583,3 +1583,43 @@ def test_package_collection_infinite_recursion(testdir):
testdir.copy_example("collect/package_infinite_recursion")
result = testdir.runpytest()
result.stdout.fnmatch_lines("*1 passed*")


def test_package_with_modules(testdir):
"""
.
└── root
├── __init__.py
├── sub1
│ ├── __init__.py
│ └── sub1_1
│ ├── __init__.py
│ └── test_in_sub1.py
└── sub2
└── test
└── test_in_sub2.py
"""
root = testdir.mkpydir("root")
sub1 = root.mkdir("sub1")
sub1.ensure("__init__.py")
sub1_test = sub1.mkdir("sub1_1")
sub1_test.ensure("__init__.py")
sub2 = root.mkdir("sub2")
sub2_test = sub2.mkdir("sub2")

sub1_test.join("test_in_sub1.py").write("def test_1(): pass")
sub2_test.join("test_in_sub2.py").write("def test_2(): pass")

# Execute from .
result = testdir.runpytest("-v", "-s")
result.assert_outcomes(passed=2)

# Execute from . with one argument "root"
result = testdir.runpytest("-v", "-s", "root")
result.assert_outcomes(passed=2)

# Chdir into package's root and execute with no args
root.chdir()
result = testdir.runpytest("-v", "-s")
result.assert_outcomes(passed=2)

0 comments on commit 64faa41

Please sign in to comment.