Skip to content

Commit 9f9b7f4

Browse files
authored
Merge pull request #13522 from bluetech/pytester-subprocess-plugins
pytester: a couple of fixes for `pytester.plugins` in subprocess mode
2 parents 5a7a91b + d32a345 commit 9f9b7f4

File tree

3 files changed

+41
-9
lines changed

3 files changed

+41
-9
lines changed

changelog/13522.bugfix.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Fixed :fixture:`pytester` in subprocess mode ignored all :attr`pytester.plugins <pytest.Pytester.plugins>` except the first.
2+
3+
Fixed :fixture:`pytester` in subprocess mode silently ignored non-str :attr:`pytester.plugins <pytest.Pytester.plugins>`.
4+
Now it errors instead.
5+
If you are affected by this, specify the plugin by name, or switch the affected tests to use :func:`pytester.runpytest_inprocess <pytest.Pytester.runpytest_inprocess>` explicitly instead.

src/_pytest/pytester.py

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -682,9 +682,11 @@ def __init__(
682682
self._name = name
683683
self._path: Path = tmp_path_factory.mktemp(name, numbered=True)
684684
#: A list of plugins to use with :py:meth:`parseconfig` and
685-
#: :py:meth:`runpytest`. Initially this is an empty list but plugins can
686-
#: be added to the list. The type of items to add to the list depends on
687-
#: the method using them so refer to them for details.
685+
#: :py:meth:`runpytest`. Initially this is an empty list but plugins can
686+
#: be added to the list.
687+
#:
688+
#: When running in subprocess mode, specify plugins by name (str) - adding
689+
#: plugin objects directly is not supported.
688690
self.plugins: list[str | _PluggyPlugin] = []
689691
self._sys_path_snapshot = SysPathsSnapshot()
690692
self._sys_modules_snapshot = self.__take_sys_modules_snapshot()
@@ -1229,10 +1231,9 @@ def parseconfig(self, *args: str | os.PathLike[str]) -> Config:
12291231
"""
12301232
import _pytest.config
12311233

1232-
new_args = self._ensure_basetemp(args)
1233-
new_args = [str(x) for x in new_args]
1234+
new_args = [str(x) for x in self._ensure_basetemp(args)]
12341235

1235-
config = _pytest.config._prepareconfig(new_args, self.plugins) # type: ignore[arg-type]
1236+
config = _pytest.config._prepareconfig(new_args, self.plugins)
12361237
# we don't know what the test will do with this half-setup config
12371238
# object and thus we make sure it gets unconfigured properly in any
12381239
# case (otherwise capturing could still be active, for example)
@@ -1494,9 +1495,13 @@ def runpytest_subprocess(
14941495
__tracebackhide__ = True
14951496
p = make_numbered_dir(root=self.path, prefix="runpytest-", mode=0o700)
14961497
args = (f"--basetemp={p}", *args)
1497-
plugins = [x for x in self.plugins if isinstance(x, str)]
1498-
if plugins:
1499-
args = ("-p", plugins[0], *args)
1498+
for plugin in self.plugins:
1499+
if not isinstance(plugin, str):
1500+
raise ValueError(
1501+
f"Specifying plugins as objects is not supported in pytester subprocess mode; "
1502+
f"specify by name instead: {plugin}"
1503+
)
1504+
args = ("-p", plugin, *args)
15001505
args = self._getpytestargs() + args
15011506
return self.run(*args, timeout=timeout)
15021507

testing/test_pytester.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -834,3 +834,25 @@ def test_two():
834834
result.assert_outcomes(passed=1, deselected=1)
835835
# If deselected is not passed, it is not checked at all.
836836
result.assert_outcomes(passed=1)
837+
838+
839+
def test_pytester_subprocess_with_string_plugins(pytester: Pytester) -> None:
840+
"""Test that pytester.runpytest_subprocess is OK with named (string)
841+
`.plugins`."""
842+
pytester.plugins = ["pytester"]
843+
844+
result = pytester.runpytest_subprocess()
845+
assert result.ret == ExitCode.NO_TESTS_COLLECTED
846+
847+
848+
def test_pytester_subprocess_with_non_string_plugins(pytester: Pytester) -> None:
849+
"""Test that pytester.runpytest_subprocess fails with a proper error given
850+
non-string `.plugins`."""
851+
852+
class MyPlugin:
853+
pass
854+
855+
pytester.plugins = [MyPlugin()]
856+
857+
with pytest.raises(ValueError, match="plugins as objects is not supported"):
858+
pytester.runpytest_subprocess()

0 commit comments

Comments
 (0)