diff --git a/py/test/collect.py b/py/test/collect.py index bf20d071b..46ab8b1e0 100644 --- a/py/test/collect.py +++ b/py/test/collect.py @@ -448,8 +448,11 @@ class Directory(FSCollector): def consider_dir(self, path, usefilters=None): if usefilters is not None: APIWARN("0.99", "usefilters argument not needed") - return self._config.pytestplugins.call_each( - 'pytest_collect_directory', path=path, parent=self) + res = self._config.pytestplugins.call_firstresult( + 'pytest_collect_recurse', path=path, parent=self) + if res is None or res: + return self._config.pytestplugins.call_each( + 'pytest_collect_directory', path=path, parent=self) from py.__.test.runner import basic_run_report, forked_run_report class Item(Node): diff --git a/py/test/plugin/pytest_plugintester.py b/py/test/plugin/pytest_plugintester.py index a71567fbd..eb3986dbb 100644 --- a/py/test/plugin/pytest_plugintester.py +++ b/py/test/plugin/pytest_plugintester.py @@ -123,8 +123,16 @@ class PytestPluginHooks: def pytest_collect_file(self, path, parent): """ return Collection node or None. """ + def pytest_collect_recurse(self, path, parent): + """ return True/False to cause/prevent recursion into given directory. + return None if you do not want to make the decision. + """ + + def pytest_collect_directory(self, path, parent): + """ return Collection node or None. """ + def pytest_pymodule_makeitem(self, modcol, name, obj): - """ return custom item/collector or None. """ + """ return custom item/collector for a python object in a module, or None. """ # from pytest_terminal plugin def pytest_report_teststatus(self, event): diff --git a/py/test/testing/test_collect.py b/py/test/testing/test_collect.py index 048de632d..e59fd238a 100644 --- a/py/test/testing/test_collect.py +++ b/py/test/testing/test_collect.py @@ -197,6 +197,22 @@ class TestCustomConftests: assert item.name == "hello.xxx" assert item.__class__.__name__ == "CustomItem" + def test_avoid_directory_on_option(self, testdir): + testdir.makeconftest(""" + class ConftestPlugin: + def pytest_addoption(self, parser): + parser.addoption("--XX", action="store_true", default=False) + def pytest_collect_recurse(self, path, parent): + return parent._config.getvalue("XX") + """) + testdir.mkdir("hello") + evrec = testdir.inline_run(testdir.tmpdir) + names = [rep.colitem.name for rep in evrec.getnamed("collectionreport")] + assert 'hello' not in names + evrec = testdir.inline_run(testdir.tmpdir, "--XX") + names = [rep.colitem.name for rep in evrec.getnamed("collectionreport")] + assert 'hello' in names + class TestCollectorReprs: def test_repr_metainfo_basic_item(self, testdir): modcol = testdir.getmodulecol("")