Skip to content

Commit 76d1523

Browse files
authored
Merge pull request #10988 from nicoddemus/initial-testpaths-10987
Consider testpaths for initial conftests
2 parents 7840323 + 4cc05e7 commit 76d1523

File tree

7 files changed

+76
-12
lines changed

7 files changed

+76
-12
lines changed

.github/workflows/stale.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ name: close needs-information issues
22
on:
33
schedule:
44
- cron: "30 1 * * *"
5-
workflow_dispatch:
5+
workflow_dispatch:
66

77
jobs:
88
close-issues:

changelog/10169.bugfix.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix bug where very long option names could cause pytest to break with ``OSError: [Errno 36] File name too long`` on some systems.

changelog/10987.bugfix.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
:confval:`testpaths` is now honored to load root ``conftests``.

doc/en/reference/reference.rst

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1713,13 +1713,12 @@ passed multiple times. The expected format is ``name=value``. For example::
17131713
17141714
.. confval:: testpaths
17151715

1716-
1717-
17181716
Sets list of directories that should be searched for tests when
17191717
no specific directories, files or test ids are given in the command line when
17201718
executing pytest from the :ref:`rootdir <rootdir>` directory.
17211719
File system paths may use shell-style wildcards, including the recursive
17221720
``**`` pattern.
1721+
17231722
Useful when all project tests are in a known location to speed up
17241723
test collection and to avoid picking up undesired tests by accident.
17251724

@@ -1728,8 +1727,17 @@ passed multiple times. The expected format is ``name=value``. For example::
17281727
[pytest]
17291728
testpaths = testing doc
17301729
1731-
This tells pytest to only look for tests in ``testing`` and ``doc``
1732-
directories when executing from the root directory.
1730+
This configuration means that executing:
1731+
1732+
.. code-block:: console
1733+
1734+
pytest
1735+
1736+
has the same practical effects as executing:
1737+
1738+
.. code-block:: console
1739+
1740+
pytest testing doc
17331741
17341742
17351743
.. confval:: tmp_path_retention_count
@@ -1744,7 +1752,7 @@ passed multiple times. The expected format is ``name=value``. For example::
17441752
[pytest]
17451753
tmp_path_retention_count = 3
17461754
1747-
Default: 3
1755+
Default: ``3``
17481756

17491757

17501758
.. confval:: tmp_path_retention_policy
@@ -1763,7 +1771,7 @@ passed multiple times. The expected format is ``name=value``. For example::
17631771
[pytest]
17641772
tmp_path_retention_policy = "all"
17651773
1766-
Default: all
1774+
Default: ``all``
17671775

17681776

17691777
.. confval:: usefixtures

src/_pytest/config/__init__.py

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -526,7 +526,10 @@ def pytest_configure(self, config: "Config") -> None:
526526
# Internal API for local conftest plugin handling.
527527
#
528528
def _set_initial_conftests(
529-
self, namespace: argparse.Namespace, rootpath: Path
529+
self,
530+
namespace: argparse.Namespace,
531+
rootpath: Path,
532+
testpaths_ini: Sequence[str],
530533
) -> None:
531534
"""Load initial conftest files given a preparsed "namespace".
532535
@@ -543,7 +546,7 @@ def _set_initial_conftests(
543546
)
544547
self._noconftest = namespace.noconftest
545548
self._using_pyargs = namespace.pyargs
546-
testpaths = namespace.file_or_dir
549+
testpaths = namespace.file_or_dir + testpaths_ini
547550
foundanchor = False
548551
for testpath in testpaths:
549552
path = str(testpath)
@@ -552,7 +555,14 @@ def _set_initial_conftests(
552555
if i != -1:
553556
path = path[:i]
554557
anchor = absolutepath(current / path)
555-
if anchor.exists(): # we found some file object
558+
559+
# Ensure we do not break if what appears to be an anchor
560+
# is in fact a very long option (#10169).
561+
try:
562+
anchor_exists = anchor.exists()
563+
except OSError: # pragma: no cover
564+
anchor_exists = False
565+
if anchor_exists:
556566
self._try_load_conftest(anchor, namespace.importmode, rootpath)
557567
foundanchor = True
558568
if not foundanchor:
@@ -1131,7 +1141,9 @@ def _processopt(self, opt: "Argument") -> None:
11311141
@hookimpl(trylast=True)
11321142
def pytest_load_initial_conftests(self, early_config: "Config") -> None:
11331143
self.pluginmanager._set_initial_conftests(
1134-
early_config.known_args_namespace, rootpath=early_config.rootpath
1144+
early_config.known_args_namespace,
1145+
rootpath=early_config.rootpath,
1146+
testpaths_ini=self.getini("testpaths"),
11351147
)
11361148

11371149
def _initini(self, args: Sequence[str]) -> None:

testing/test_collection.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1247,6 +1247,48 @@ def test_collect_pyargs_with_testpaths(
12471247
result.stdout.fnmatch_lines(["*1 passed in*"])
12481248

12491249

1250+
def test_initial_conftests_with_testpaths(pytester: Pytester) -> None:
1251+
"""The testpaths ini option should load conftests in those paths as 'initial' (#10987)."""
1252+
p = pytester.mkdir("some_path")
1253+
p.joinpath("conftest.py").write_text(
1254+
textwrap.dedent(
1255+
"""
1256+
def pytest_sessionstart(session):
1257+
raise Exception("pytest_sessionstart hook successfully run")
1258+
"""
1259+
)
1260+
)
1261+
pytester.makeini(
1262+
"""
1263+
[pytest]
1264+
testpaths = some_path
1265+
"""
1266+
)
1267+
result = pytester.runpytest()
1268+
result.stdout.fnmatch_lines(
1269+
"INTERNALERROR* Exception: pytest_sessionstart hook successfully run"
1270+
)
1271+
1272+
1273+
def test_large_option_breaks_initial_conftests(pytester: Pytester) -> None:
1274+
"""Long option values do not break initial conftests handling (#10169)."""
1275+
option_value = "x" * 1024 * 1000
1276+
pytester.makeconftest(
1277+
"""
1278+
def pytest_addoption(parser):
1279+
parser.addoption("--xx", default=None)
1280+
"""
1281+
)
1282+
pytester.makepyfile(
1283+
f"""
1284+
def test_foo(request):
1285+
assert request.config.getoption("xx") == {option_value!r}
1286+
"""
1287+
)
1288+
result = pytester.runpytest(f"--xx={option_value}")
1289+
assert result.ret == 0
1290+
1291+
12501292
def test_collect_symlink_file_arg(pytester: Pytester) -> None:
12511293
"""Collect a direct symlink works even if it does not match python_files (#4325)."""
12521294
real = pytester.makepyfile(

testing/test_conftest.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ def __init__(self) -> None:
3535
self.importmode = "prepend"
3636

3737
namespace = cast(argparse.Namespace, Namespace())
38-
conftest._set_initial_conftests(namespace, rootpath=Path(args[0]))
38+
conftest._set_initial_conftests(namespace, rootpath=Path(args[0]), testpaths_ini=[])
3939

4040

4141
@pytest.mark.usefixtures("_sys_snapshot")

0 commit comments

Comments
 (0)