From 01ac13a77d6cd56a5ac20756542e59a7b14129a0 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sun, 9 Jan 2022 13:58:29 +0200 Subject: [PATCH 01/34] config: split _getconftestmodules and _loadconftestmodules Previously, the `_getconftestmodules` function was used both to load conftest modules for a path (during `pytest_load_initial_conftests`), and to retrieve conftest modules for a path (during hook dispatch and for fetching `collect_ignore`). This made things muddy - it is usually nicer to have clear separation between "command" and "query" functions, when they occur in separate phases. So split into "load" and "get". Currently, `gethookproxy` still loads conftest itself. I hope to change this in the future. --- src/_pytest/config/__init__.py | 32 +++++++--------- src/_pytest/main.py | 11 ++++-- testing/python/fixtures.py | 4 +- testing/test_config.py | 17 +++------ testing/test_conftest.py | 70 +++++++++++----------------------- 5 files changed, 50 insertions(+), 84 deletions(-) diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index 2b6f250f3..8dbaf7c70 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -581,26 +581,25 @@ class PytestPluginManager(PluginManager): def _try_load_conftest( self, anchor: Path, importmode: Union[str, ImportMode], rootpath: Path ) -> None: - self._getconftestmodules(anchor, importmode, rootpath) + self._loadconftestmodules(anchor, importmode, rootpath) # let's also consider test* subdirs if anchor.is_dir(): for x in anchor.glob("test*"): if x.is_dir(): - self._getconftestmodules(x, importmode, rootpath) + self._loadconftestmodules(x, importmode, rootpath) - def _getconftestmodules( + def _loadconftestmodules( self, path: Path, importmode: Union[str, ImportMode], rootpath: Path - ) -> Sequence[types.ModuleType]: + ) -> None: if self._noconftest: - return [] + return directory = self._get_directory(path) # Optimization: avoid repeated searches in the same directory. # Assumes always called with same importmode and rootpath. - existing_clist = self._dirpath2confmods.get(directory) - if existing_clist is not None: - return existing_clist + if directory in self._dirpath2confmods: + return # XXX these days we may rather want to use config.rootpath # and allow users to opt into looking into the rootdir parent @@ -613,16 +612,17 @@ class PytestPluginManager(PluginManager): mod = self._importconftest(conftestpath, importmode, rootpath) clist.append(mod) self._dirpath2confmods[directory] = clist - return clist + + def _getconftestmodules(self, path: Path) -> Sequence[types.ModuleType]: + directory = self._get_directory(path) + return self._dirpath2confmods.get(directory, ()) def _rget_with_confmod( self, name: str, path: Path, - importmode: Union[str, ImportMode], - rootpath: Path, ) -> Tuple[types.ModuleType, Any]: - modules = self._getconftestmodules(path, importmode, rootpath=rootpath) + modules = self._getconftestmodules(path) for mod in reversed(modules): try: return mod, getattr(mod, name) @@ -1562,13 +1562,9 @@ class Config: else: return self._getini_unknown_type(name, type, value) - def _getconftest_pathlist( - self, name: str, path: Path, rootpath: Path - ) -> Optional[List[Path]]: + def _getconftest_pathlist(self, name: str, path: Path) -> Optional[List[Path]]: try: - mod, relroots = self.pluginmanager._rget_with_confmod( - name, path, self.getoption("importmode"), rootpath - ) + mod, relroots = self.pluginmanager._rget_with_confmod(name, path) except KeyError: return None assert mod.__file__ is not None diff --git a/src/_pytest/main.py b/src/_pytest/main.py index 4c3c9aed4..fd3836736 100644 --- a/src/_pytest/main.py +++ b/src/_pytest/main.py @@ -376,7 +376,7 @@ def _in_venv(path: Path) -> bool: def pytest_ignore_collect(collection_path: Path, config: Config) -> Optional[bool]: ignore_paths = config._getconftest_pathlist( - "collect_ignore", path=collection_path.parent, rootpath=config.rootpath + "collect_ignore", path=collection_path.parent ) ignore_paths = ignore_paths or [] excludeopt = config.getoption("ignore") @@ -387,7 +387,7 @@ def pytest_ignore_collect(collection_path: Path, config: Config) -> Optional[boo return True ignore_globs = config._getconftest_pathlist( - "collect_ignore_glob", path=collection_path.parent, rootpath=config.rootpath + "collect_ignore_glob", path=collection_path.parent ) ignore_globs = ignore_globs or [] excludeglobopt = config.getoption("ignore_glob") @@ -551,11 +551,16 @@ class Session(nodes.FSCollector): pm = self.config.pluginmanager # Check if we have the common case of running # hooks with all conftest.py files. - my_conftestmodules = pm._getconftestmodules( + # + # TODO: pytest relies on this call to load non-initial conftests. This + # is incidental. It will be better to load conftests at a more + # well-defined place. + pm._loadconftestmodules( path, self.config.getoption("importmode"), rootpath=self.config.rootpath, ) + my_conftestmodules = pm._getconftestmodules(path) remove_mods = pm._conftest_plugins.difference(my_conftestmodules) if remove_mods: # One or more conftests are not in use at this fspath. diff --git a/testing/python/fixtures.py b/testing/python/fixtures.py index 191689d1c..7c0282772 100644 --- a/testing/python/fixtures.py +++ b/testing/python/fixtures.py @@ -2103,9 +2103,7 @@ class TestAutouseManagement: reprec = pytester.inline_run("-v", "-s", "--confcutdir", pytester.path) reprec.assertoutcome(passed=8) config = reprec.getcalls("pytest_unconfigure")[0].config - values = config.pluginmanager._getconftestmodules( - p, importmode="prepend", rootpath=pytester.path - )[0].values + values = config.pluginmanager._getconftestmodules(p)[0].values assert values == ["fin_a1", "fin_a2", "fin_b1", "fin_b2"] * 2 def test_scope_ordering(self, pytester: Pytester) -> None: diff --git a/testing/test_config.py b/testing/test_config.py index 43561000c..04161f238 100644 --- a/testing/test_config.py +++ b/testing/test_config.py @@ -642,18 +642,11 @@ class TestConfigAPI: p = tmp_path.joinpath("conftest.py") p.write_text(f"mylist = {['.', str(somepath)]}", encoding="utf-8") config = pytester.parseconfigure(p) - assert ( - config._getconftest_pathlist("notexist", path=tmp_path, rootpath=tmp_path) - is None - ) - pl = ( - config._getconftest_pathlist("mylist", path=tmp_path, rootpath=tmp_path) - or [] - ) - print(pl) - assert len(pl) == 2 - assert pl[0] == tmp_path - assert pl[1] == somepath + assert config._getconftest_pathlist("notexist", path=tmp_path) is None + assert config._getconftest_pathlist("mylist", path=tmp_path) == [ + tmp_path, + somepath, + ] @pytest.mark.parametrize("maybe_type", ["not passed", "None", '"string"']) def test_addini(self, pytester: Pytester, maybe_type: str) -> None: diff --git a/testing/test_conftest.py b/testing/test_conftest.py index 427831507..cfc2d577b 100644 --- a/testing/test_conftest.py +++ b/testing/test_conftest.py @@ -62,28 +62,22 @@ class TestConftestValueAccessGlobal: def test_basic_init(self, basedir: Path) -> None: conftest = PytestPluginManager() p = basedir / "adir" - assert ( - conftest._rget_with_confmod("a", p, importmode="prepend", rootpath=basedir)[ - 1 - ] - == 1 - ) + conftest._loadconftestmodules(p, importmode="prepend", rootpath=basedir) + assert conftest._rget_with_confmod("a", p)[1] == 1 def test_immediate_initialiation_and_incremental_are_the_same( self, basedir: Path ) -> None: conftest = PytestPluginManager() assert not len(conftest._dirpath2confmods) - conftest._getconftestmodules( - basedir, importmode="prepend", rootpath=Path(basedir) - ) + conftest._loadconftestmodules(basedir, importmode="prepend", rootpath=basedir) snap1 = len(conftest._dirpath2confmods) assert snap1 == 1 - conftest._getconftestmodules( + conftest._loadconftestmodules( basedir / "adir", importmode="prepend", rootpath=basedir ) assert len(conftest._dirpath2confmods) == snap1 + 1 - conftest._getconftestmodules( + conftest._loadconftestmodules( basedir / "b", importmode="prepend", rootpath=basedir ) assert len(conftest._dirpath2confmods) == snap1 + 2 @@ -91,33 +85,23 @@ class TestConftestValueAccessGlobal: def test_value_access_not_existing(self, basedir: Path) -> None: conftest = ConftestWithSetinitial(basedir) with pytest.raises(KeyError): - conftest._rget_with_confmod( - "a", basedir, importmode="prepend", rootpath=Path(basedir) - ) + conftest._rget_with_confmod("a", basedir) def test_value_access_by_path(self, basedir: Path) -> None: conftest = ConftestWithSetinitial(basedir) adir = basedir / "adir" - assert ( - conftest._rget_with_confmod( - "a", adir, importmode="prepend", rootpath=basedir - )[1] - == 1 - ) - assert ( - conftest._rget_with_confmod( - "a", adir / "b", importmode="prepend", rootpath=basedir - )[1] - == 1.5 + conftest._loadconftestmodules(adir, importmode="prepend", rootpath=basedir) + assert conftest._rget_with_confmod("a", adir)[1] == 1 + conftest._loadconftestmodules( + adir / "b", importmode="prepend", rootpath=basedir ) + assert conftest._rget_with_confmod("a", adir / "b")[1] == 1.5 def test_value_access_with_confmod(self, basedir: Path) -> None: startdir = basedir / "adir" / "b" startdir.joinpath("xx").mkdir() conftest = ConftestWithSetinitial(startdir) - mod, value = conftest._rget_with_confmod( - "a", startdir, importmode="prepend", rootpath=Path(basedir) - ) + mod, value = conftest._rget_with_confmod("a", startdir) assert value == 1.5 assert mod.__file__ is not None path = Path(mod.__file__) @@ -143,9 +127,7 @@ def test_doubledash_considered(pytester: Pytester) -> None: conf.joinpath("conftest.py").touch() conftest = PytestPluginManager() conftest_setinitial(conftest, [conf.name, conf.name]) - values = conftest._getconftestmodules( - conf, importmode="prepend", rootpath=pytester.path - ) + values = conftest._getconftestmodules(conf) assert len(values) == 1 @@ -192,26 +174,22 @@ def test_conftestcutdir(pytester: Pytester) -> None: p = pytester.mkdir("x") conftest = PytestPluginManager() conftest_setinitial(conftest, [pytester.path], confcutdir=p) - values = conftest._getconftestmodules( - p, importmode="prepend", rootpath=pytester.path - ) + conftest._loadconftestmodules(p, importmode="prepend", rootpath=pytester.path) + values = conftest._getconftestmodules(p) assert len(values) == 0 - values = conftest._getconftestmodules( + conftest._loadconftestmodules( conf.parent, importmode="prepend", rootpath=pytester.path ) + values = conftest._getconftestmodules(conf.parent) assert len(values) == 0 assert not conftest.has_plugin(str(conf)) # but we can still import a conftest directly conftest._importconftest(conf, importmode="prepend", rootpath=pytester.path) - values = conftest._getconftestmodules( - conf.parent, importmode="prepend", rootpath=pytester.path - ) + values = conftest._getconftestmodules(conf.parent) assert values[0].__file__ is not None assert values[0].__file__.startswith(str(conf)) # and all sub paths get updated properly - values = conftest._getconftestmodules( - p, importmode="prepend", rootpath=pytester.path - ) + values = conftest._getconftestmodules(p) assert len(values) == 1 assert values[0].__file__ is not None assert values[0].__file__.startswith(str(conf)) @@ -221,9 +199,7 @@ def test_conftestcutdir_inplace_considered(pytester: Pytester) -> None: conf = pytester.makeconftest("") conftest = PytestPluginManager() conftest_setinitial(conftest, [conf.parent], confcutdir=conf.parent) - values = conftest._getconftestmodules( - conf.parent, importmode="prepend", rootpath=pytester.path - ) + values = conftest._getconftestmodules(conf.parent) assert len(values) == 1 assert values[0].__file__ is not None assert values[0].__file__.startswith(str(conf)) @@ -433,10 +409,8 @@ def test_conftest_import_order(pytester: Pytester, monkeypatch: MonkeyPatch) -> conftest = PytestPluginManager() conftest._confcutdir = pytester.path monkeypatch.setattr(conftest, "_importconftest", impct) - mods = cast( - List[Path], - conftest._getconftestmodules(sub, importmode="prepend", rootpath=pytester.path), - ) + conftest._loadconftestmodules(sub, importmode="prepend", rootpath=pytester.path) + mods = cast(List[Path], conftest._getconftestmodules(sub)) expected = [ct1, ct2] assert mods == expected From cc0adf6bf3c9f356e3473ff8a21004b9c1fb2b93 Mon Sep 17 00:00:00 2001 From: Christoph Anton Mitterer Date: Sat, 5 Aug 2023 21:30:41 +0200 Subject: [PATCH 02/34] doc: update information about assertion messages (#11285) It was pointed out[0] that the previous behaviour has been obsoleted by commit 37bd1e03cb77a26ae80873a8725c87d57fda987c. [0] https://github.com/pytest-dev/pytest/issues/11265#issuecomment-1666581197 Signed-off-by: Christoph Anton Mitterer --- doc/en/how-to/assert.rst | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/doc/en/how-to/assert.rst b/doc/en/how-to/assert.rst index 1b10c1313..d99a1ce5c 100644 --- a/doc/en/how-to/assert.rst +++ b/doc/en/how-to/assert.rst @@ -54,14 +54,13 @@ operators. (See :ref:`tbreportdemo`). This allows you to use the idiomatic python constructs without boilerplate code while not losing introspection information. -However, if you specify a message with the assertion like this: +If a message is specified with the assertion like this: .. code-block:: python assert a % 2 == 0, "value was odd, should be even" -then no assertion introspection takes places at all and the message -will be simply shown in the traceback. +it is printed alongside the assertion introspection in the traceback. See :ref:`assert-details` for more information on assertion introspection. From 1c04a925039a528a996bf0433ef604086d6c432e Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Sun, 6 Aug 2023 12:39:11 +0200 Subject: [PATCH 03/34] doc: Link pytest.main to how-to guide (#11287) --- doc/en/reference/reference.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/en/reference/reference.rst b/doc/en/reference/reference.rst index ea008110e..a6d7cfdd4 100644 --- a/doc/en/reference/reference.rst +++ b/doc/en/reference/reference.rst @@ -82,6 +82,8 @@ pytest.exit pytest.main ~~~~~~~~~~~ +**Tutorial**: :ref:`pytest.main-usage` + .. autofunction:: pytest.main pytest.param From e8a8a5f320ad7a9fc1d58ab74c2425e923634f60 Mon Sep 17 00:00:00 2001 From: Sadra Barikbin Date: Sun, 6 Aug 2023 17:29:54 +0330 Subject: [PATCH 04/34] python: fix scope assignment for indirect parameter sets (#11277) Previously, when assigning a scope for a fully-indirect parameter set, when there are multiple fixturedefs for a param (i.e. same-name fixture chain), the highest scope was used, but it should be the lowest scope, since that's the effective scope of the fixture. --- changelog/11277.bugfix.rst | 2 ++ src/_pytest/fixtures.py | 2 +- src/_pytest/python.py | 4 +-- testing/python/metafunc.py | 62 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 67 insertions(+), 3 deletions(-) create mode 100644 changelog/11277.bugfix.rst diff --git a/changelog/11277.bugfix.rst b/changelog/11277.bugfix.rst new file mode 100644 index 000000000..43370561e --- /dev/null +++ b/changelog/11277.bugfix.rst @@ -0,0 +1,2 @@ +Fixed a bug that when there are multiple fixtures for an indirect parameter, +the scope of the highest-scope fixture is picked for the parameter set, instead of that of the one with the narrowest scope. diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index 00c2a8ef4..6e99ec188 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -492,7 +492,7 @@ class FixtureRequest: node: Optional[Union[nodes.Item, nodes.Collector]] = self._pyfuncitem elif scope is Scope.Package: # FIXME: _fixturedef is not defined on FixtureRequest (this class), - # but on FixtureRequest (a subclass). + # but on SubRequest (a subclass). node = get_scope_package(self._pyfuncitem, self._fixturedef) # type: ignore[attr-defined] else: node = get_scope_node(self._pyfuncitem, scope) diff --git a/src/_pytest/python.py b/src/_pytest/python.py index c0c16d4d0..ae42e390f 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -1516,7 +1516,7 @@ def _find_parametrized_scope( if all_arguments_are_fixtures: fixturedefs = arg2fixturedefs or {} used_scopes = [ - fixturedef[0]._scope + fixturedef[-1]._scope for name, fixturedef in fixturedefs.items() if name in argnames ] @@ -1682,7 +1682,7 @@ class Function(PyobjMixin, nodes.Item): :param config: The pytest Config object. :param callspec: - If given, this is function has been parametrized and the callspec contains + If given, this function has been parametrized and the callspec contains meta information about the parametrization. :param callobj: If given, the object which will be called when the Function is invoked, diff --git a/testing/python/metafunc.py b/testing/python/metafunc.py index bb4ae9d9a..4c066a89d 100644 --- a/testing/python/metafunc.py +++ b/testing/python/metafunc.py @@ -151,6 +151,7 @@ class TestMetafunc: module_fix=[DummyFixtureDef(Scope.Module)], class_fix=[DummyFixtureDef(Scope.Class)], func_fix=[DummyFixtureDef(Scope.Function)], + mixed_fix=[DummyFixtureDef(Scope.Module), DummyFixtureDef(Scope.Class)], ), ) @@ -187,6 +188,7 @@ class TestMetafunc: ) == Scope.Module ) + assert find_scope(["mixed_fix"], indirect=True) == Scope.Class def test_parametrize_and_id(self) -> None: def func(x, y): @@ -1503,6 +1505,66 @@ class TestMetafuncFunctional: result = pytester.runpytest() assert result.ret == 0 + def test_reordering_with_scopeless_and_just_indirect_parametrization( + self, pytester: Pytester + ) -> None: + pytester.makeconftest( + """ + import pytest + + @pytest.fixture(scope="package") + def fixture1(): + pass + """ + ) + pytester.makepyfile( + """ + import pytest + + @pytest.fixture(scope="module") + def fixture0(): + pass + + @pytest.fixture(scope="module") + def fixture1(fixture0): + pass + + @pytest.mark.parametrize("fixture1", [0], indirect=True) + def test_0(fixture1): + pass + + @pytest.fixture(scope="module") + def fixture(): + pass + + @pytest.mark.parametrize("fixture", [0], indirect=True) + def test_1(fixture): + pass + + def test_2(): + pass + + class Test: + @pytest.fixture(scope="class") + def fixture(self, fixture): + pass + + @pytest.mark.parametrize("fixture", [0], indirect=True) + def test_3(self, fixture): + pass + """ + ) + result = pytester.runpytest("-v") + assert result.ret == 0 + result.stdout.fnmatch_lines( + [ + "*test_0*", + "*test_1*", + "*test_2*", + "*test_3*", + ] + ) + class TestMetafuncFunctionalAuto: """Tests related to automatically find out the correct scope for From 84a342e27c1b3ba218b9c31ed9aeddba843ef36c Mon Sep 17 00:00:00 2001 From: Christoph Anton Mitterer Date: Sun, 6 Aug 2023 17:39:31 +0200 Subject: [PATCH 05/34] doc: parametrize() can be called multiple times only on different args Signed-off-by: Christoph Anton Mitterer --- src/_pytest/python.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/_pytest/python.py b/src/_pytest/python.py index c0c16d4d0..b3f7d408b 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -1239,8 +1239,9 @@ class Metafunc: during the collection phase. If you need to setup expensive resources see about setting indirect to do it rather than at test setup time. - Can be called multiple times, in which case each call parametrizes all - previous parametrizations, e.g. + Can be called multiple times per test function (but only on different + argument names), in which case each call parametrizes all previous + parametrizations, e.g. :: From 1cc58ed67ff9e9c90b6b39154763138779ebceaf Mon Sep 17 00:00:00 2001 From: Christoph Anton Mitterer Date: Sun, 6 Aug 2023 17:43:37 +0200 Subject: [PATCH 06/34] improve exception message on duplicate parametrization Signed-off-by: Christoph Anton Mitterer --- src/_pytest/python.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/_pytest/python.py b/src/_pytest/python.py index b3f7d408b..fef952b66 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -1148,7 +1148,7 @@ class CallSpec2: arg2scope = self._arg2scope.copy() for arg, val in zip(argnames, valset): if arg in params or arg in funcargs: - raise ValueError(f"duplicate {arg!r}") + raise ValueError(f"duplicate parametrization of {arg!r}") valtype_for_arg = valtypes[arg] if valtype_for_arg == "params": params[arg] = val From 9c67b7aeb60d7abbea782018e73a93d6c8bbef16 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 7 Aug 2023 03:39:31 +0000 Subject: [PATCH 07/34] build(deps): Bump django in /testing/plugins_integration Bumps [django](https://github.com/django/django) from 4.2.3 to 4.2.4. - [Commits](https://github.com/django/django/compare/4.2.3...4.2.4) --- updated-dependencies: - dependency-name: django dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- testing/plugins_integration/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/plugins_integration/requirements.txt b/testing/plugins_integration/requirements.txt index cf580b7cc..d46300fe0 100644 --- a/testing/plugins_integration/requirements.txt +++ b/testing/plugins_integration/requirements.txt @@ -1,5 +1,5 @@ anyio[curio,trio]==3.7.1 -django==4.2.3 +django==4.2.4 pytest-asyncio==0.21.1 pytest-bdd==6.1.1 pytest-cov==4.1.0 From 09b78737a5bde23eb488d5d6649bf966c5809176 Mon Sep 17 00:00:00 2001 From: Sadra Barikbin Date: Wed, 9 Aug 2023 20:43:45 +0330 Subject: [PATCH 08/34] Move `fixtures.py::add_funcarg_pseudo_fixture_def` to `Metafunc.parametrize` (#11220) To remove fixtures.py::add_funcargs_pseudo_fixture_def and add its logic i.e. registering funcargs as params and making corresponding fixturedefs, right to Metafunc.parametrize in which parametrization takes place. To remove funcargs from metafunc attributes as we populate metafunc params and make pseudo fixturedefs simultaneously and there's no need to keep funcargs separately. --- src/_pytest/fixtures.py | 88 ----------------------- src/_pytest/python.py | 102 +++++++++++++++++++------- testing/example_scripts/issue_519.py | 4 +- testing/python/metafunc.py | 103 +++++++++++++++++++++++---- 4 files changed, 167 insertions(+), 130 deletions(-) diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index 6e99ec188..be0dce17c 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -63,7 +63,6 @@ from _pytest.pathlib import bestrelpath from _pytest.scope import _ScopeName from _pytest.scope import HIGH_SCOPES from _pytest.scope import Scope -from _pytest.stash import StashKey if TYPE_CHECKING: @@ -147,89 +146,6 @@ def get_scope_node( assert_never(scope) -# Used for storing artificial fixturedefs for direct parametrization. -name2pseudofixturedef_key = StashKey[Dict[str, "FixtureDef[Any]"]]() - - -def add_funcarg_pseudo_fixture_def( - collector: nodes.Collector, metafunc: "Metafunc", fixturemanager: "FixtureManager" -) -> None: - import _pytest.python - - # This function will transform all collected calls to functions - # if they use direct funcargs (i.e. direct parametrization) - # because we want later test execution to be able to rely on - # an existing FixtureDef structure for all arguments. - # XXX we can probably avoid this algorithm if we modify CallSpec2 - # to directly care for creating the fixturedefs within its methods. - if not metafunc._calls[0].funcargs: - # This function call does not have direct parametrization. - return - # Collect funcargs of all callspecs into a list of values. - arg2params: Dict[str, List[object]] = {} - arg2scope: Dict[str, Scope] = {} - for callspec in metafunc._calls: - for argname, argvalue in callspec.funcargs.items(): - assert argname not in callspec.params - callspec.params[argname] = argvalue - arg2params_list = arg2params.setdefault(argname, []) - callspec.indices[argname] = len(arg2params_list) - arg2params_list.append(argvalue) - if argname not in arg2scope: - scope = callspec._arg2scope.get(argname, Scope.Function) - arg2scope[argname] = scope - callspec.funcargs.clear() - - # Register artificial FixtureDef's so that later at test execution - # time we can rely on a proper FixtureDef to exist for fixture setup. - arg2fixturedefs = metafunc._arg2fixturedefs - for argname, valuelist in arg2params.items(): - # If we have a scope that is higher than function, we need - # to make sure we only ever create an according fixturedef on - # a per-scope basis. We thus store and cache the fixturedef on the - # node related to the scope. - scope = arg2scope[argname] - node = None - if scope is not Scope.Function: - node = get_scope_node(collector, scope) - if node is None: - # If used class scope and there is no class, use module-level - # collector (for now). - if scope is Scope.Class: - assert isinstance(collector, _pytest.python.Module) - node = collector - # If used package scope and there is no package, use session - # (for now). - elif scope is Scope.Package: - node = collector.session - else: - assert False, f"Unhandled missing scope: {scope}" - if node is None: - name2pseudofixturedef = None - else: - default: Dict[str, FixtureDef[Any]] = {} - name2pseudofixturedef = node.stash.setdefault( - name2pseudofixturedef_key, default - ) - if name2pseudofixturedef is not None and argname in name2pseudofixturedef: - arg2fixturedefs[argname] = [name2pseudofixturedef[argname]] - else: - fixturedef = FixtureDef( - fixturemanager=fixturemanager, - baseid="", - argname=argname, - func=get_direct_param_fixture_func, - scope=arg2scope[argname], - params=valuelist, - unittest=False, - ids=None, - _ispytest=True, - ) - arg2fixturedefs[argname] = [fixturedef] - if name2pseudofixturedef is not None: - name2pseudofixturedef[argname] = fixturedef - - def getfixturemarker(obj: object) -> Optional["FixtureFunctionMarker"]: """Return fixturemarker or None if it doesn't exist or raised exceptions.""" @@ -365,10 +281,6 @@ def reorder_items_atscope( return items_done -def get_direct_param_fixture_func(request: "FixtureRequest") -> Any: - return request.param - - @dataclasses.dataclass(frozen=True) class FuncFixtureInfo: """Fixture-related information for a fixture-requesting item (e.g. test diff --git a/src/_pytest/python.py b/src/_pytest/python.py index 02d6c1749..eb4512fe5 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -40,7 +40,6 @@ from _pytest._code.code import Traceback from _pytest._io import TerminalWriter from _pytest._io.saferepr import saferepr from _pytest.compat import ascii_escaped -from _pytest.compat import assert_never from _pytest.compat import get_default_arg_names from _pytest.compat import get_real_func from _pytest.compat import getimfunc @@ -59,7 +58,10 @@ from _pytest.config.argparsing import Parser from _pytest.deprecated import check_ispytest from _pytest.deprecated import INSTANCE_COLLECTOR from _pytest.deprecated import NOSE_SUPPORT_METHOD +from _pytest.fixtures import FixtureDef +from _pytest.fixtures import FixtureRequest from _pytest.fixtures import FuncFixtureInfo +from _pytest.fixtures import get_scope_node from _pytest.main import Session from _pytest.mark import MARK_GEN from _pytest.mark import ParameterSet @@ -77,6 +79,7 @@ from _pytest.pathlib import parts from _pytest.pathlib import visit from _pytest.scope import _ScopeName from _pytest.scope import Scope +from _pytest.stash import StashKey from _pytest.warning_types import PytestCollectionWarning from _pytest.warning_types import PytestReturnNotNoneWarning from _pytest.warning_types import PytestUnhandledCoroutineWarning @@ -493,13 +496,11 @@ class PyCollector(PyobjMixin, nodes.Collector): if not metafunc._calls: yield Function.from_parent(self, name=name, fixtureinfo=fixtureinfo) else: - # Add funcargs() as fixturedefs to fixtureinfo.arg2fixturedefs. - fm = self.session._fixturemanager - fixtures.add_funcarg_pseudo_fixture_def(self, metafunc, fm) - - # Add_funcarg_pseudo_fixture_def may have shadowed some fixtures - # with direct parametrization, so make sure we update what the - # function really needs. + # Direct parametrizations taking place in module/class-specific + # `metafunc.parametrize` calls may have shadowed some fixtures, so make sure + # we update what the function really needs a.k.a its fixture closure. Note that + # direct parametrizations using `@pytest.mark.parametrize` have already been considered + # into making the closure using `ignore_args` arg to `getfixtureclosure`. fixtureinfo.prune_dependency_tree() for callspec in metafunc._calls: @@ -1116,11 +1117,8 @@ class CallSpec2: and stored in item.callspec. """ - # arg name -> arg value which will be passed to the parametrized test - # function (direct parameterization). - funcargs: Dict[str, object] = dataclasses.field(default_factory=dict) - # arg name -> arg value which will be passed to a fixture of the same name - # (indirect parametrization). + # arg name -> arg value which will be passed to a fixture or pseudo-fixture + # of the same name. (indirect or direct parametrization respectively) params: Dict[str, object] = dataclasses.field(default_factory=dict) # arg name -> arg index. indices: Dict[str, int] = dataclasses.field(default_factory=dict) @@ -1134,7 +1132,6 @@ class CallSpec2: def setmulti( self, *, - valtypes: Mapping[str, "Literal['params', 'funcargs']"], argnames: Iterable[str], valset: Iterable[object], id: str, @@ -1142,24 +1139,16 @@ class CallSpec2: scope: Scope, param_index: int, ) -> "CallSpec2": - funcargs = self.funcargs.copy() params = self.params.copy() indices = self.indices.copy() arg2scope = self._arg2scope.copy() for arg, val in zip(argnames, valset): - if arg in params or arg in funcargs: + if arg in params: raise ValueError(f"duplicate parametrization of {arg!r}") - valtype_for_arg = valtypes[arg] - if valtype_for_arg == "params": - params[arg] = val - elif valtype_for_arg == "funcargs": - funcargs[arg] = val - else: - assert_never(valtype_for_arg) + params[arg] = val indices[arg] = param_index arg2scope[arg] = scope return CallSpec2( - funcargs=funcargs, params=params, indices=indices, _arg2scope=arg2scope, @@ -1178,6 +1167,14 @@ class CallSpec2: return "-".join(self._idlist) +def get_direct_param_fixture_func(request: FixtureRequest) -> Any: + return request.param + + +# Used for storing pseudo fixturedefs for direct parametrization. +name2pseudofixturedef_key = StashKey[Dict[str, FixtureDef[Any]]]() + + @final class Metafunc: """Objects passed to the :hook:`pytest_generate_tests` hook. @@ -1320,8 +1317,6 @@ class Metafunc: self._validate_if_using_arg_names(argnames, indirect) - arg_values_types = self._resolve_arg_value_types(argnames, indirect) - # Use any already (possibly) generated ids with parametrize Marks. if _param_mark and _param_mark._param_ids_from: generated_ids = _param_mark._param_ids_from._param_ids_generated @@ -1336,6 +1331,60 @@ class Metafunc: if _param_mark and _param_mark._param_ids_from and generated_ids is None: object.__setattr__(_param_mark._param_ids_from, "_param_ids_generated", ids) + # Add funcargs as fixturedefs to fixtureinfo.arg2fixturedefs by registering + # artificial "pseudo" FixtureDef's so that later at test execution time we can + # rely on a proper FixtureDef to exist for fixture setup. + arg2fixturedefs = self._arg2fixturedefs + node = None + # If we have a scope that is higher than function, we need + # to make sure we only ever create an according fixturedef on + # a per-scope basis. We thus store and cache the fixturedef on the + # node related to the scope. + if scope_ is not Scope.Function: + collector = self.definition.parent + assert collector is not None + node = get_scope_node(collector, scope_) + if node is None: + # If used class scope and there is no class, use module-level + # collector (for now). + if scope_ is Scope.Class: + assert isinstance(collector, _pytest.python.Module) + node = collector + # If used package scope and there is no package, use session + # (for now). + elif scope_ is Scope.Package: + node = collector.session + else: + assert False, f"Unhandled missing scope: {scope}" + if node is None: + name2pseudofixturedef = None + else: + default: Dict[str, FixtureDef[Any]] = {} + name2pseudofixturedef = node.stash.setdefault( + name2pseudofixturedef_key, default + ) + arg_values_types = self._resolve_arg_value_types(argnames, indirect) + for argname in argnames: + if arg_values_types[argname] == "params": + continue + if name2pseudofixturedef is not None and argname in name2pseudofixturedef: + fixturedef = name2pseudofixturedef[argname] + else: + fixturedef = FixtureDef( + fixturemanager=self.definition.session._fixturemanager, + baseid="", + argname=argname, + func=get_direct_param_fixture_func, + scope=scope_, + params=None, + unittest=False, + ids=None, + _ispytest=True, + ) + if name2pseudofixturedef is not None: + name2pseudofixturedef[argname] = fixturedef + arg2fixturedefs[argname] = [fixturedef] + # Create the new calls: if we are parametrize() multiple times (by applying the decorator # more than once) then we accumulate those calls generating the cartesian product # of all calls. @@ -1345,7 +1394,6 @@ class Metafunc: zip(ids, parametersets) ): newcallspec = callspec.setmulti( - valtypes=arg_values_types, argnames=argnames, valset=param_set.values, id=param_id, diff --git a/testing/example_scripts/issue_519.py b/testing/example_scripts/issue_519.py index e44367fca..73437ef7b 100644 --- a/testing/example_scripts/issue_519.py +++ b/testing/example_scripts/issue_519.py @@ -22,13 +22,13 @@ def checked_order(): assert order == [ ("issue_519.py", "fix1", "arg1v1"), ("test_one[arg1v1-arg2v1]", "fix2", "arg2v1"), - ("test_two[arg1v1-arg2v1]", "fix2", "arg2v1"), ("test_one[arg1v1-arg2v2]", "fix2", "arg2v2"), + ("test_two[arg1v1-arg2v1]", "fix2", "arg2v1"), ("test_two[arg1v1-arg2v2]", "fix2", "arg2v2"), ("issue_519.py", "fix1", "arg1v2"), ("test_one[arg1v2-arg2v1]", "fix2", "arg2v1"), - ("test_two[arg1v2-arg2v1]", "fix2", "arg2v1"), ("test_one[arg1v2-arg2v2]", "fix2", "arg2v2"), + ("test_two[arg1v2-arg2v1]", "fix2", "arg2v1"), ("test_two[arg1v2-arg2v2]", "fix2", "arg2v2"), ] diff --git a/testing/python/metafunc.py b/testing/python/metafunc.py index 4c066a89d..4ee9e32d6 100644 --- a/testing/python/metafunc.py +++ b/testing/python/metafunc.py @@ -23,6 +23,7 @@ from _pytest.compat import getfuncargnames from _pytest.compat import NOTSET from _pytest.outcomes import fail from _pytest.pytester import Pytester +from _pytest.python import Function from _pytest.python import IdMaker from _pytest.scope import Scope @@ -33,11 +34,19 @@ class TestMetafunc: # on the funcarg level, so we don't need a full blown # initialization. class FuncFixtureInfoMock: - name2fixturedefs = None + name2fixturedefs: Dict[str, List[fixtures.FixtureDef[object]]] = {} def __init__(self, names): self.names_closure = names + @dataclasses.dataclass + class FixtureManagerMock: + config: Any + + @dataclasses.dataclass + class SessionMock: + _fixturemanager: FixtureManagerMock + @dataclasses.dataclass class DefinitionMock(python.FunctionDefinition): _nodeid: str @@ -46,6 +55,8 @@ class TestMetafunc: names = getfuncargnames(func) fixtureinfo: Any = FuncFixtureInfoMock(names) definition: Any = DefinitionMock._create(obj=func, _nodeid="mock::nodeid") + definition._fixtureinfo = fixtureinfo + definition.session = SessionMock(FixtureManagerMock({})) return python.Metafunc(definition, fixtureinfo, config, _ispytest=True) def test_no_funcargs(self) -> None: @@ -98,7 +109,7 @@ class TestMetafunc: # When the input is an iterator, only len(args) are taken, # so the bad Exc isn't reached. metafunc.parametrize("x", [1, 2], ids=gen()) # type: ignore[arg-type] - assert [(x.funcargs, x.id) for x in metafunc._calls] == [ + assert [(x.params, x.id) for x in metafunc._calls] == [ ({"x": 1}, "0"), ({"x": 2}, "2"), ] @@ -714,8 +725,6 @@ class TestMetafunc: metafunc.parametrize("x", [1], indirect=True) metafunc.parametrize("y", [2, 3], indirect=True) assert len(metafunc._calls) == 2 - assert metafunc._calls[0].funcargs == {} - assert metafunc._calls[1].funcargs == {} assert metafunc._calls[0].params == dict(x=1, y=2) assert metafunc._calls[1].params == dict(x=1, y=3) @@ -727,8 +736,10 @@ class TestMetafunc: metafunc = self.Metafunc(func) metafunc.parametrize("x, y", [("a", "b")], indirect=["x"]) - assert metafunc._calls[0].funcargs == dict(y="b") - assert metafunc._calls[0].params == dict(x="a") + assert metafunc._calls[0].params == dict(x="a", y="b") + # Since `y` is a direct parameter, its pseudo-fixture would + # be registered. + assert list(metafunc._arg2fixturedefs.keys()) == ["y"] def test_parametrize_indirect_list_all(self) -> None: """#714""" @@ -738,8 +749,8 @@ class TestMetafunc: metafunc = self.Metafunc(func) metafunc.parametrize("x, y", [("a", "b")], indirect=["x", "y"]) - assert metafunc._calls[0].funcargs == {} assert metafunc._calls[0].params == dict(x="a", y="b") + assert list(metafunc._arg2fixturedefs.keys()) == [] def test_parametrize_indirect_list_empty(self) -> None: """#714""" @@ -749,8 +760,8 @@ class TestMetafunc: metafunc = self.Metafunc(func) metafunc.parametrize("x, y", [("a", "b")], indirect=[]) - assert metafunc._calls[0].funcargs == dict(x="a", y="b") - assert metafunc._calls[0].params == {} + assert metafunc._calls[0].params == dict(x="a", y="b") + assert list(metafunc._arg2fixturedefs.keys()) == ["x", "y"] def test_parametrize_indirect_wrong_type(self) -> None: def func(x, y): @@ -944,9 +955,9 @@ class TestMetafunc: metafunc = self.Metafunc(lambda x: None) metafunc.parametrize("x", [1, 2]) assert len(metafunc._calls) == 2 - assert metafunc._calls[0].funcargs == dict(x=1) + assert metafunc._calls[0].params == dict(x=1) assert metafunc._calls[0].id == "1" - assert metafunc._calls[1].funcargs == dict(x=2) + assert metafunc._calls[1].params == dict(x=2) assert metafunc._calls[1].id == "2" def test_parametrize_onearg_indirect(self) -> None: @@ -961,11 +972,45 @@ class TestMetafunc: metafunc = self.Metafunc(lambda x, y: None) metafunc.parametrize(("x", "y"), [(1, 2), (3, 4)]) assert len(metafunc._calls) == 2 - assert metafunc._calls[0].funcargs == dict(x=1, y=2) + assert metafunc._calls[0].params == dict(x=1, y=2) assert metafunc._calls[0].id == "1-2" - assert metafunc._calls[1].funcargs == dict(x=3, y=4) + assert metafunc._calls[1].params == dict(x=3, y=4) assert metafunc._calls[1].id == "3-4" + def test_high_scoped_parametrize_reordering(self, pytester: Pytester) -> None: + pytester.makepyfile( + """ + import pytest + + @pytest.mark.parametrize("arg2", [3, 4]) + @pytest.mark.parametrize("arg1", [0, 1, 2], scope='module') + def test1(arg1, arg2): + pass + + def test2(): + pass + + @pytest.mark.parametrize("arg1", [0, 1, 2], scope='module') + def test3(arg1): + pass + """ + ) + result = pytester.runpytest("--collect-only") + result.stdout.re_match_lines( + [ + r" ", + r" ", + r" ", + r" ", + r" ", + r" ", + r" ", + r" ", + r" ", + r" ", + ] + ) + def test_parametrize_multiple_times(self, pytester: Pytester) -> None: pytester.makepyfile( """ @@ -1505,6 +1550,38 @@ class TestMetafuncFunctional: result = pytester.runpytest() assert result.ret == 0 + def test_parametrize_module_level_test_with_class_scope( + self, pytester: Pytester + ) -> None: + """ + Test that a class-scoped parametrization without a corresponding `Class` + gets module scope, i.e. we only create a single FixtureDef for it per module. + """ + module = pytester.makepyfile( + """ + import pytest + + @pytest.mark.parametrize("x", [0, 1], scope="class") + def test_1(x): + pass + + @pytest.mark.parametrize("x", [1, 2], scope="module") + def test_2(x): + pass + """ + ) + test_1_0, _, test_2_0, _ = pytester.genitems((pytester.getmodulecol(module),)) + + assert isinstance(test_1_0, Function) + assert test_1_0.name == "test_1[0]" + test_1_fixture_x = test_1_0._fixtureinfo.name2fixturedefs["x"][-1] + + assert isinstance(test_2_0, Function) + assert test_2_0.name == "test_2[1]" + test_2_fixture_x = test_2_0._fixtureinfo.name2fixturedefs["x"][-1] + + assert test_1_fixture_x is test_2_fixture_x + def test_reordering_with_scopeless_and_just_indirect_parametrization( self, pytester: Pytester ) -> None: From 3ad3fc6b8f480656e727ce7e89ad84eb9a6735e7 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Wed, 9 Aug 2023 20:34:16 +0300 Subject: [PATCH 09/34] python: use clearer terminology for `_resolve_arg_value_types` --- src/_pytest/python.py | 38 ++++++++++++++++++++------------------ 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/src/_pytest/python.py b/src/_pytest/python.py index eb4512fe5..c3097b863 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -1363,9 +1363,9 @@ class Metafunc: name2pseudofixturedef = node.stash.setdefault( name2pseudofixturedef_key, default ) - arg_values_types = self._resolve_arg_value_types(argnames, indirect) + arg_directness = self._resolve_args_directness(argnames, indirect) for argname in argnames: - if arg_values_types[argname] == "params": + if arg_directness[argname] == "indirect": continue if name2pseudofixturedef is not None and argname in name2pseudofixturedef: fixturedef = name2pseudofixturedef[argname] @@ -1470,28 +1470,30 @@ class Metafunc: return list(itertools.islice(ids, num_ids)) - def _resolve_arg_value_types( + def _resolve_args_directness( self, argnames: Sequence[str], indirect: Union[bool, Sequence[str]], - ) -> Dict[str, "Literal['params', 'funcargs']"]: - """Resolve if each parametrized argument must be considered a - parameter to a fixture or a "funcarg" to the function, based on the - ``indirect`` parameter of the parametrized() call. + ) -> Dict[str, Literal["indirect", "direct"]]: + """Resolve if each parametrized argument must be considered an indirect + parameter to a fixture of the same name, or a direct parameter to the + parametrized function, based on the ``indirect`` parameter of the + parametrized() call. - :param List[str] argnames: List of argument names passed to ``parametrize()``. - :param indirect: Same as the ``indirect`` parameter of ``parametrize()``. - :rtype: Dict[str, str] - A dict mapping each arg name to either: - * "params" if the argname should be the parameter of a fixture of the same name. - * "funcargs" if the argname should be a parameter to the parametrized test function. + :param argnames: + List of argument names passed to ``parametrize()``. + :param indirect: + Same as the ``indirect`` parameter of ``parametrize()``. + :returns + A dict mapping each arg name to either "indirect" or "direct". """ + arg_directness: Dict[str, Literal["indirect", "direct"]] if isinstance(indirect, bool): - valtypes: Dict[str, Literal["params", "funcargs"]] = dict.fromkeys( - argnames, "params" if indirect else "funcargs" + arg_directness = dict.fromkeys( + argnames, "indirect" if indirect else "direct" ) elif isinstance(indirect, Sequence): - valtypes = dict.fromkeys(argnames, "funcargs") + arg_directness = dict.fromkeys(argnames, "direct") for arg in indirect: if arg not in argnames: fail( @@ -1500,7 +1502,7 @@ class Metafunc: ), pytrace=False, ) - valtypes[arg] = "params" + arg_directness[arg] = "indirect" else: fail( "In {func}: expected Sequence or boolean for indirect, got {type}".format( @@ -1508,7 +1510,7 @@ class Metafunc: ), pytrace=False, ) - return valtypes + return arg_directness def _validate_if_using_arg_names( self, From 47c0fc3d78a6db8bbe6c298dec76084142f59171 Mon Sep 17 00:00:00 2001 From: Reagan Lee <96998476+reaganjlee@users.noreply.github.com> Date: Thu, 10 Aug 2023 16:36:22 -0700 Subject: [PATCH 10/34] tests --- testing/test_assertrewrite.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/testing/test_assertrewrite.py b/testing/test_assertrewrite.py index e1b71ded6..d85c8bed6 100644 --- a/testing/test_assertrewrite.py +++ b/testing/test_assertrewrite.py @@ -685,6 +685,21 @@ class TestAssertionRewrite: assert msg is not None assert " < 0" in msg + def test_assert_handling_raise_in__iter__(self) -> None: + def f() -> None: + class A: + def __iter__(self): + raise TypeError("user message") + + def __eq__(self, o: object) -> bool: + return self is o + + assert A() == A() + + msg = getmsg(f) + assert msg is not None + assert "Unexpected exception" in msg + def test_formatchar(self) -> None: def f() -> None: assert "%test" == "test" # type: ignore[comparison-overlap] From e938580257e8120dabbea789d5b7a3dd3354d0a3 Mon Sep 17 00:00:00 2001 From: Reagan Lee <96998476+reaganjlee@users.noreply.github.com> Date: Thu, 10 Aug 2023 17:37:48 -0700 Subject: [PATCH 11/34] check for user-generated exceptions --- src/_pytest/assertion/util.py | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/src/_pytest/assertion/util.py b/src/_pytest/assertion/util.py index fc5dfdbd5..47244b688 100644 --- a/src/_pytest/assertion/util.py +++ b/src/_pytest/assertion/util.py @@ -132,8 +132,14 @@ def isiterable(obj: Any) -> bool: try: iter(obj) return not istext(obj) - except TypeError: - return False + except Exception as e: + if ( + isinstance(e, TypeError) + and (len(e.args) == 1) + and "iter() returned non-iterator of type" in str(e.args[0]) + ): + return False + raise ValueError(f"Unexpected exception {e!r} while testing object {obj!r}") def has_default_eq( @@ -195,13 +201,20 @@ def assertrepr_compare( explanation = _notin_text(left, right, verbose) except outcomes.Exit: raise - except Exception: - explanation = [ - "(pytest_assertion plugin: representation of details failed: {}.".format( - _pytest._code.ExceptionInfo.from_current()._getreprcrash() - ), - " Probably an object has a faulty __repr__.)", - ] + except Exception as e: + if ( + isinstance(e, ValueError) + and (len(e.args) == 1) + and ("Unexpected exception" in str(e.args[0])) + ): + explanation = [e.args[0]] + else: + explanation = [ + "(pytest_assertion plugin: representation of details failed: {}.".format( + _pytest._code.ExceptionInfo.from_current()._getreprcrash() + ), + " Probably an object has a faulty __repr__.)", + ] if not explanation: return None From b9cb87d862bb3f841d67723ac5717ce90b219dc2 Mon Sep 17 00:00:00 2001 From: Reagan Lee <96998476+reaganjlee@users.noreply.github.com> Date: Thu, 10 Aug 2023 17:43:01 -0700 Subject: [PATCH 12/34] simplify code / take out user-gen typeerror case --- src/_pytest/assertion/util.py | 8 ++------ testing/test_assertrewrite.py | 2 +- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/src/_pytest/assertion/util.py b/src/_pytest/assertion/util.py index 47244b688..22eec1809 100644 --- a/src/_pytest/assertion/util.py +++ b/src/_pytest/assertion/util.py @@ -132,13 +132,9 @@ def isiterable(obj: Any) -> bool: try: iter(obj) return not istext(obj) + except TypeError: + return False except Exception as e: - if ( - isinstance(e, TypeError) - and (len(e.args) == 1) - and "iter() returned non-iterator of type" in str(e.args[0]) - ): - return False raise ValueError(f"Unexpected exception {e!r} while testing object {obj!r}") diff --git a/testing/test_assertrewrite.py b/testing/test_assertrewrite.py index d85c8bed6..b4e3e5d53 100644 --- a/testing/test_assertrewrite.py +++ b/testing/test_assertrewrite.py @@ -689,7 +689,7 @@ class TestAssertionRewrite: def f() -> None: class A: def __iter__(self): - raise TypeError("user message") + raise ValueError() def __eq__(self, o: object) -> bool: return self is o From d2dc8a70b593b61a013ae3eba99bb3f10e82eb65 Mon Sep 17 00:00:00 2001 From: Reagan Lee <96998476+reaganjlee@users.noreply.github.com> Date: Fri, 11 Aug 2023 09:48:53 -0700 Subject: [PATCH 13/34] changelog --- changelog/7966.bugfix.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog/7966.bugfix.rst diff --git a/changelog/7966.bugfix.rst b/changelog/7966.bugfix.rst new file mode 100644 index 000000000..40cad46c6 --- /dev/null +++ b/changelog/7966.bugfix.rst @@ -0,0 +1 @@ +Assertion rewrite mechanism now gives a seperate, more detailed error message from failures within __iter__. From ec1053cc162250e42ae220ebe91c3bf00b22b084 Mon Sep 17 00:00:00 2001 From: Reagan Lee <96998476+reaganjlee@users.noreply.github.com> Date: Fri, 11 Aug 2023 10:03:19 -0700 Subject: [PATCH 14/34] error msg --- src/_pytest/assertion/util.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/_pytest/assertion/util.py b/src/_pytest/assertion/util.py index 22eec1809..613a40b97 100644 --- a/src/_pytest/assertion/util.py +++ b/src/_pytest/assertion/util.py @@ -135,7 +135,9 @@ def isiterable(obj: Any) -> bool: except TypeError: return False except Exception as e: - raise ValueError(f"Unexpected exception {e!r} while testing object {obj!r}") + raise ValueError( + f"Unexpected exception {e!r} while testing object {obj!r}. Probably an issue with __iter__" + ) def has_default_eq( From c0cf822ca1d5d6ac74f46ddccbe377c254c6084a Mon Sep 17 00:00:00 2001 From: Reagan Lee <96998476+reaganjlee@users.noreply.github.com> Date: Fri, 11 Aug 2023 10:03:19 -0700 Subject: [PATCH 15/34] improve error msg and test --- src/_pytest/assertion/util.py | 9 ++++++--- testing/test_assertrewrite.py | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/_pytest/assertion/util.py b/src/_pytest/assertion/util.py index 613a40b97..d20c2363e 100644 --- a/src/_pytest/assertion/util.py +++ b/src/_pytest/assertion/util.py @@ -136,7 +136,10 @@ def isiterable(obj: Any) -> bool: return False except Exception as e: raise ValueError( - f"Unexpected exception {e!r} while testing object {obj!r}. Probably an issue with __iter__" + [ + f"pytest_assertion plugin: unexpected exception {e!r} while testing object {obj!r}", + ", probably from __iter__", + ] ) @@ -203,9 +206,9 @@ def assertrepr_compare( if ( isinstance(e, ValueError) and (len(e.args) == 1) - and ("Unexpected exception" in str(e.args[0])) + and ("__iter__" in str(e.args[0])) ): - explanation = [e.args[0]] + explanation = e.args[0] else: explanation = [ "(pytest_assertion plugin: representation of details failed: {}.".format( diff --git a/testing/test_assertrewrite.py b/testing/test_assertrewrite.py index b4e3e5d53..62c6bb8d4 100644 --- a/testing/test_assertrewrite.py +++ b/testing/test_assertrewrite.py @@ -698,7 +698,7 @@ class TestAssertionRewrite: msg = getmsg(f) assert msg is not None - assert "Unexpected exception" in msg + assert "__iter__" in msg and "__repr__" not in msg def test_formatchar(self) -> None: def f() -> None: From 9e164fc4fe46bbd43ac87fc30d0d6935f7e4d28b Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sun, 16 Jul 2023 00:37:33 +0300 Subject: [PATCH 16/34] fixtures: make FixtureRequest abstract, add TopRequest subclass Fix #11218. --- changelog/11218.trivial.rst | 5 + src/_pytest/doctest.py | 8 +- src/_pytest/fixtures.py | 201 ++++++++++++++++++++++-------------- src/_pytest/python.py | 2 +- testing/python/fixtures.py | 25 ++--- testing/test_legacypath.py | 3 +- 6 files changed, 148 insertions(+), 96 deletions(-) create mode 100644 changelog/11218.trivial.rst diff --git a/changelog/11218.trivial.rst b/changelog/11218.trivial.rst new file mode 100644 index 000000000..772054856 --- /dev/null +++ b/changelog/11218.trivial.rst @@ -0,0 +1,5 @@ +(This entry is meant to assist plugins which access private pytest internals to instantiate ``FixtureRequest`` objects.) + +:class:`~pytest.FixtureRequest` is now an abstract class which can't be instantiated directly. +A new concrete ``TopRequest`` subclass of ``FixtureRequest`` has been added for the ``request`` fixture in test functions, +as counterpart to the existing ``SubRequest`` subclass for the ``request`` fixture in fixture functions. diff --git a/src/_pytest/doctest.py b/src/_pytest/doctest.py index a37f1d2ac..e6f666dda 100644 --- a/src/_pytest/doctest.py +++ b/src/_pytest/doctest.py @@ -32,7 +32,7 @@ from _pytest.compat import safe_getattr from _pytest.config import Config from _pytest.config.argparsing import Parser from _pytest.fixtures import fixture -from _pytest.fixtures import FixtureRequest +from _pytest.fixtures import TopRequest from _pytest.nodes import Collector from _pytest.nodes import Item from _pytest.outcomes import OutcomeException @@ -261,7 +261,7 @@ class DoctestItem(Item): self.runner = runner self.dtest = dtest self.obj = None - self.fixture_request: Optional[FixtureRequest] = None + self.fixture_request: Optional[TopRequest] = None @classmethod def from_parent( # type: ignore @@ -571,7 +571,7 @@ class DoctestModule(Module): ) -def _setup_fixtures(doctest_item: DoctestItem) -> FixtureRequest: +def _setup_fixtures(doctest_item: DoctestItem) -> TopRequest: """Used by DoctestTextfile and DoctestItem to setup fixture information.""" def func() -> None: @@ -582,7 +582,7 @@ def _setup_fixtures(doctest_item: DoctestItem) -> FixtureRequest: doctest_item._fixtureinfo = fm.getfixtureinfo( # type: ignore[attr-defined] node=doctest_item, func=func, cls=None, funcargs=False ) - fixture_request = FixtureRequest(doctest_item, _ispytest=True) # type: ignore[arg-type] + fixture_request = TopRequest(doctest_item, _ispytest=True) # type: ignore[arg-type] fixture_request._fillfixtures() return fixture_request diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index be0dce17c..c7fc28adb 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -1,3 +1,4 @@ +import abc import dataclasses import functools import inspect @@ -340,26 +341,32 @@ class FuncFixtureInfo: self.names_closure[:] = sorted(closure, key=self.names_closure.index) -class FixtureRequest: - """A request for a fixture from a test or fixture function. +class FixtureRequest(abc.ABC): + """The type of the ``request`` fixture. - A request object gives access to the requesting test context and has - an optional ``param`` attribute in case the fixture is parametrized - indirectly. + A request object gives access to the requesting test context and has a + ``param`` attribute in case the fixture is parametrized. """ - def __init__(self, pyfuncitem: "Function", *, _ispytest: bool = False) -> None: + def __init__( + self, + pyfuncitem: "Function", + fixturename: Optional[str], + arg2fixturedefs: Dict[str, Sequence["FixtureDef[Any]"]], + arg2index: Dict[str, int], + fixture_defs: Dict[str, "FixtureDef[Any]"], + *, + _ispytest: bool = False, + ) -> None: check_ispytest(_ispytest) #: Fixture for which this request is being performed. - self.fixturename: Optional[str] = None - self._pyfuncitem = pyfuncitem - self._fixturemanager = pyfuncitem.session._fixturemanager - self._scope = Scope.Function + self.fixturename: Final = fixturename + self._pyfuncitem: Final = pyfuncitem # The FixtureDefs for each fixture name requested by this item. # Starts from the statically-known fixturedefs resolved during # collection. Dynamically requested fixtures (using # `request.getfixturevalue("foo")`) are added dynamically. - self._arg2fixturedefs = pyfuncitem._fixtureinfo.name2fixturedefs.copy() + self._arg2fixturedefs: Final = arg2fixturedefs # A fixture may override another fixture with the same name, e.g. a fixture # in a module can override a fixture in a conftest, a fixture in a class can # override a fixture in the module, and so on. @@ -369,10 +376,10 @@ class FixtureRequest: # The fixturedefs list in _arg2fixturedefs for a given name is ordered from # furthest to closest, so we use negative indexing -1, -2, ... to go from # last to first. - self._arg2index: Dict[str, int] = {} + self._arg2index: Final = arg2index # The evaluated argnames so far, mapping to the FixtureDef they resolved # to. - self._fixture_defs: Dict[str, FixtureDef[Any]] = {} + self._fixture_defs: Final = fixture_defs # Notes on the type of `param`: # -`request.param` is only defined in parametrized fixtures, and will raise # AttributeError otherwise. Python typing has no notion of "undefined", so @@ -383,6 +390,15 @@ class FixtureRequest: # for now just using Any. self.param: Any + @property + def _fixturemanager(self) -> "FixtureManager": + return self._pyfuncitem.session._fixturemanager + + @property + @abc.abstractmethod + def _scope(self) -> Scope: + raise NotImplementedError() + @property def scope(self) -> _ScopeName: """Scope string, one of "function", "class", "module", "package", "session".""" @@ -396,25 +412,10 @@ class FixtureRequest: return result @property + @abc.abstractmethod def node(self): """Underlying collection node (depends on current request scope).""" - scope = self._scope - if scope is Scope.Function: - # This might also be a non-function Item despite its attribute name. - node: Optional[Union[nodes.Item, nodes.Collector]] = self._pyfuncitem - elif scope is Scope.Package: - # FIXME: _fixturedef is not defined on FixtureRequest (this class), - # but on SubRequest (a subclass). - node = get_scope_package(self._pyfuncitem, self._fixturedef) # type: ignore[attr-defined] - else: - node = get_scope_node(self._pyfuncitem, scope) - if node is None and scope is Scope.Class: - # Fallback to function item itself. - node = self._pyfuncitem - assert node, 'Could not obtain a node for scope "{}" for function {!r}'.format( - scope, self._pyfuncitem - ) - return node + raise NotImplementedError() def _getnextfixturedef(self, argname: str) -> "FixtureDef[Any]": fixturedefs = self._arg2fixturedefs.get(argname, None) @@ -500,11 +501,11 @@ class FixtureRequest: """Pytest session object.""" return self._pyfuncitem.session # type: ignore[no-any-return] + @abc.abstractmethod def addfinalizer(self, finalizer: Callable[[], object]) -> None: """Add finalizer/teardown function to be called without arguments after the last test within the requesting test context finished execution.""" - # XXX usually this method is shadowed by fixturedef specific ones. - self.node.addfinalizer(finalizer) + raise NotImplementedError() def applymarker(self, marker: Union[str, MarkDecorator]) -> None: """Apply a marker to a single test function invocation. @@ -525,13 +526,6 @@ class FixtureRequest: """ raise self._fixturemanager.FixtureLookupError(None, self, msg) - def _fillfixtures(self) -> None: - item = self._pyfuncitem - fixturenames = getattr(item, "fixturenames", self.fixturenames) - for argname in fixturenames: - if argname not in item.funcargs: - item.funcargs[argname] = self.getfixturevalue(argname) - def getfixturevalue(self, argname: str) -> Any: """Dynamically run a named fixture function. @@ -665,6 +659,98 @@ class FixtureRequest: finalizer = functools.partial(fixturedef.finish, request=subrequest) subrequest.node.addfinalizer(finalizer) + +@final +class TopRequest(FixtureRequest): + """The type of the ``request`` fixture in a test function.""" + + def __init__(self, pyfuncitem: "Function", *, _ispytest: bool = False) -> None: + super().__init__( + fixturename=None, + pyfuncitem=pyfuncitem, + arg2fixturedefs=pyfuncitem._fixtureinfo.name2fixturedefs.copy(), + arg2index={}, + fixture_defs={}, + _ispytest=_ispytest, + ) + + @property + def _scope(self) -> Scope: + return Scope.Function + + @property + def node(self): + return self._pyfuncitem + + def __repr__(self) -> str: + return "" % (self.node) + + def _fillfixtures(self) -> None: + item = self._pyfuncitem + fixturenames = getattr(item, "fixturenames", self.fixturenames) + for argname in fixturenames: + if argname not in item.funcargs: + item.funcargs[argname] = self.getfixturevalue(argname) + + def addfinalizer(self, finalizer: Callable[[], object]) -> None: + self.node.addfinalizer(finalizer) + + +@final +class SubRequest(FixtureRequest): + """The type of the ``request`` fixture in a fixture function requested + (transitively) by a test function.""" + + def __init__( + self, + request: FixtureRequest, + scope: Scope, + param: Any, + param_index: int, + fixturedef: "FixtureDef[object]", + *, + _ispytest: bool = False, + ) -> None: + super().__init__( + pyfuncitem=request._pyfuncitem, + fixturename=fixturedef.argname, + fixture_defs=request._fixture_defs, + arg2fixturedefs=request._arg2fixturedefs, + arg2index=request._arg2index, + _ispytest=_ispytest, + ) + self._parent_request: Final[FixtureRequest] = request + self._scope_field: Final = scope + self._fixturedef: Final = fixturedef + if param is not NOTSET: + self.param = param + self.param_index: Final = param_index + + def __repr__(self) -> str: + return f"" + + @property + def _scope(self) -> Scope: + return self._scope_field + + @property + def node(self): + scope = self._scope + if scope is Scope.Function: + # This might also be a non-function Item despite its attribute name. + node: Optional[Union[nodes.Item, nodes.Collector]] = self._pyfuncitem + elif scope is Scope.Package: + node = get_scope_package(self._pyfuncitem, self._fixturedef) + else: + node = get_scope_node(self._pyfuncitem, scope) + if node is None and scope is Scope.Class: + # Fallback to function item itself. + node = self._pyfuncitem + assert node, 'Could not obtain a node for scope "{}" for function {!r}'.format( + scope, self._pyfuncitem + ) + return node + def _check_scope( self, argname: str, @@ -699,44 +785,7 @@ class FixtureRequest: ) return lines - def __repr__(self) -> str: - return "" % (self.node) - - -@final -class SubRequest(FixtureRequest): - """A sub request for handling getting a fixture from a test function/fixture.""" - - def __init__( - self, - request: "FixtureRequest", - scope: Scope, - param: Any, - param_index: int, - fixturedef: "FixtureDef[object]", - *, - _ispytest: bool = False, - ) -> None: - check_ispytest(_ispytest) - self._parent_request = request - self.fixturename = fixturedef.argname - if param is not NOTSET: - self.param = param - self.param_index = param_index - self._scope = scope - self._fixturedef = fixturedef - self._pyfuncitem = request._pyfuncitem - self._fixture_defs = request._fixture_defs - self._arg2fixturedefs = request._arg2fixturedefs - self._arg2index = request._arg2index - self._fixturemanager = request._fixturemanager - - def __repr__(self) -> str: - return f"" - def addfinalizer(self, finalizer: Callable[[], object]) -> None: - """Add finalizer/teardown function to be called without arguments after - the last test within the requesting test context finished execution.""" self._fixturedef.addfinalizer(finalizer) def _schedule_finalizers( diff --git a/src/_pytest/python.py b/src/_pytest/python.py index c3097b863..df1eb854d 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -1812,7 +1812,7 @@ class Function(PyobjMixin, nodes.Item): def _initrequest(self) -> None: self.funcargs: Dict[str, object] = {} - self._request = fixtures.FixtureRequest(self, _ispytest=True) + self._request = fixtures.TopRequest(self, _ispytest=True) @property def function(self): diff --git a/testing/python/fixtures.py b/testing/python/fixtures.py index 7c0282772..a8f36cb9f 100644 --- a/testing/python/fixtures.py +++ b/testing/python/fixtures.py @@ -4,10 +4,9 @@ import textwrap from pathlib import Path import pytest -from _pytest import fixtures from _pytest.compat import getfuncargnames from _pytest.config import ExitCode -from _pytest.fixtures import FixtureRequest +from _pytest.fixtures import TopRequest from _pytest.monkeypatch import MonkeyPatch from _pytest.pytester import get_public_names from _pytest.pytester import Pytester @@ -659,7 +658,7 @@ class TestRequestBasic: """ ) assert isinstance(item, Function) - req = fixtures.FixtureRequest(item, _ispytest=True) + req = TopRequest(item, _ispytest=True) assert req.function == item.obj assert req.keywords == item.keywords assert hasattr(req.module, "test_func") @@ -701,9 +700,7 @@ class TestRequestBasic: (item1,) = pytester.genitems([modcol]) assert isinstance(item1, Function) assert item1.name == "test_method" - arg2fixturedefs = fixtures.FixtureRequest( - item1, _ispytest=True - )._arg2fixturedefs + arg2fixturedefs = TopRequest(item1, _ispytest=True)._arg2fixturedefs assert len(arg2fixturedefs) == 1 assert arg2fixturedefs["something"][0].argname == "something" @@ -969,7 +966,7 @@ class TestRequestBasic: modcol = pytester.getmodulecol("def test_somefunc(): pass") (item,) = pytester.genitems([modcol]) assert isinstance(item, Function) - req = fixtures.FixtureRequest(item, _ispytest=True) + req = TopRequest(item, _ispytest=True) assert req.path == modcol.path def test_request_fixturenames(self, pytester: Pytester) -> None: @@ -1128,7 +1125,7 @@ class TestRequestMarking: """ ) assert isinstance(item1, Function) - req1 = fixtures.FixtureRequest(item1, _ispytest=True) + req1 = TopRequest(item1, _ispytest=True) assert "xfail" not in item1.keywords req1.applymarker(pytest.mark.xfail) assert "xfail" in item1.keywords @@ -4036,7 +4033,7 @@ class TestScopeOrdering: ) items, _ = pytester.inline_genitems() assert isinstance(items[0], Function) - request = FixtureRequest(items[0], _ispytest=True) + request = TopRequest(items[0], _ispytest=True) assert request.fixturenames == "m1 f1".split() def test_func_closure_with_native_fixtures( @@ -4085,7 +4082,7 @@ class TestScopeOrdering: ) items, _ = pytester.inline_genitems() assert isinstance(items[0], Function) - request = FixtureRequest(items[0], _ispytest=True) + request = TopRequest(items[0], _ispytest=True) # order of fixtures based on their scope and position in the parameter list assert ( request.fixturenames @@ -4113,7 +4110,7 @@ class TestScopeOrdering: ) items, _ = pytester.inline_genitems() assert isinstance(items[0], Function) - request = FixtureRequest(items[0], _ispytest=True) + request = TopRequest(items[0], _ispytest=True) assert request.fixturenames == "m1 f1".split() def test_func_closure_scopes_reordered(self, pytester: Pytester) -> None: @@ -4147,7 +4144,7 @@ class TestScopeOrdering: ) items, _ = pytester.inline_genitems() assert isinstance(items[0], Function) - request = FixtureRequest(items[0], _ispytest=True) + request = TopRequest(items[0], _ispytest=True) assert request.fixturenames == "s1 m1 c1 f2 f1".split() def test_func_closure_same_scope_closer_root_first( @@ -4190,7 +4187,7 @@ class TestScopeOrdering: ) items, _ = pytester.inline_genitems() assert isinstance(items[0], Function) - request = FixtureRequest(items[0], _ispytest=True) + request = TopRequest(items[0], _ispytest=True) assert request.fixturenames == "p_sub m_conf m_sub m_test f1".split() def test_func_closure_all_scopes_complex(self, pytester: Pytester) -> None: @@ -4235,7 +4232,7 @@ class TestScopeOrdering: ) items, _ = pytester.inline_genitems() assert isinstance(items[0], Function) - request = FixtureRequest(items[0], _ispytest=True) + request = TopRequest(items[0], _ispytest=True) assert request.fixturenames == "s1 p1 m1 m2 c1 f2 f1".split() def test_multiple_packages(self, pytester: Pytester) -> None: diff --git a/testing/test_legacypath.py b/testing/test_legacypath.py index b32036d14..b4fd1bf2c 100644 --- a/testing/test_legacypath.py +++ b/testing/test_legacypath.py @@ -2,6 +2,7 @@ from pathlib import Path import pytest from _pytest.compat import LEGACY_PATH +from _pytest.fixtures import TopRequest from _pytest.legacypath import TempdirFactory from _pytest.legacypath import Testdir @@ -91,7 +92,7 @@ def test_fixturerequest_getmodulepath(pytester: pytest.Pytester) -> None: modcol = pytester.getmodulecol("def test_somefunc(): pass") (item,) = pytester.genitems([modcol]) assert isinstance(item, pytest.Function) - req = pytest.FixtureRequest(item, _ispytest=True) + req = TopRequest(item, _ispytest=True) assert req.path == modcol.path assert req.fspath == modcol.fspath # type: ignore[attr-defined] From 1827d8d5f9164da3cf8a7f0a22ea6c36814fdfd4 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sat, 12 Aug 2023 18:02:13 +0300 Subject: [PATCH 17/34] doc: fix a few `pytest.mark.xfail` nits Refs #9027, #10094. --- doc/en/reference/reference.rst | 8 +++++--- src/_pytest/mark/structures.py | 4 +++- src/_pytest/outcomes.py | 3 +++ 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/doc/en/reference/reference.rst b/doc/en/reference/reference.rst index a6d7cfdd4..5a2458bcb 100644 --- a/doc/en/reference/reference.rst +++ b/doc/en/reference/reference.rst @@ -237,7 +237,7 @@ pytest.mark.xfail Marks a test function as *expected to fail*. -.. py:function:: pytest.mark.xfail(condition=None, *, reason=None, raises=None, run=True, strict=False) +.. py:function:: pytest.mark.xfail(condition=None, *, reason=None, raises=None, run=True, strict=xfail_strict) :type condition: bool or str :param condition: @@ -249,10 +249,10 @@ Marks a test function as *expected to fail*. :keyword Type[Exception] raises: Exception subclass (or tuple of subclasses) expected to be raised by the test function; other exceptions will fail the test. :keyword bool run: - If the test function should actually be executed. If ``False``, the function will always xfail and will + Whether the test function should actually be executed. If ``False``, the function will always xfail and will not be executed (useful if a function is segfaulting). :keyword bool strict: - * If ``False`` (the default) the function will be shown in the terminal output as ``xfailed`` if it fails + * If ``False`` the function will be shown in the terminal output as ``xfailed`` if it fails and as ``xpass`` if it passes. In both cases this will not cause the test suite to fail as a whole. This is particularly useful to mark *flaky* tests (tests that fail at random) to be tackled later. * If ``True``, the function will be shown in the terminal output as ``xfailed`` if it fails, but if it @@ -260,6 +260,8 @@ Marks a test function as *expected to fail*. that are always failing and there should be a clear indication if they unexpectedly start to pass (for example a new release of a library fixes a known bug). + Defaults to :confval:`xfail_strict`, which is ``False`` by default. + Custom marks ~~~~~~~~~~~~ diff --git a/src/_pytest/mark/structures.py b/src/_pytest/mark/structures.py index d6e426567..bbde68644 100644 --- a/src/_pytest/mark/structures.py +++ b/src/_pytest/mark/structures.py @@ -461,7 +461,9 @@ if TYPE_CHECKING: *conditions: Union[str, bool], reason: str = ..., run: bool = ..., - raises: Union[Type[BaseException], Tuple[Type[BaseException], ...]] = ..., + raises: Union[ + None, Type[BaseException], Tuple[Type[BaseException], ...] + ] = ..., strict: bool = ..., ) -> MarkDecorator: ... diff --git a/src/_pytest/outcomes.py b/src/_pytest/outcomes.py index 7dab4499b..a8984c5b9 100644 --- a/src/_pytest/outcomes.py +++ b/src/_pytest/outcomes.py @@ -233,6 +233,9 @@ def xfail(reason: str = "") -> NoReturn: This function should be called only during testing (setup, call or teardown). + No other code is executed after using ``xfail()`` (it is implemented + internally by raising an exception). + :param reason: The message to show the user as reason for the xfail. From 73d754bd74ae8ddf86eb90cda29545cef495e927 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 15 Aug 2023 07:56:42 +0000 Subject: [PATCH 18/34] [pre-commit.ci] pre-commit autoupdate (#11313) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/pre-commit/mirrors-mypy: v1.4.1 → v1.5.0](https://github.com/pre-commit/mirrors-mypy/compare/v1.4.1...v1.5.0) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index be6d08221..d9d488dd1 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -56,7 +56,7 @@ repos: hooks: - id: python-use-type-annotations - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.4.1 + rev: v1.5.0 hooks: - id: mypy files: ^(src/|testing/) From 176d728b7b351fd967be1ff63deee042d5c234e2 Mon Sep 17 00:00:00 2001 From: ubaumann Date: Fri, 18 Aug 2023 23:34:40 +0200 Subject: [PATCH 19/34] add nuts to plugin list Adding https://github.com/network-unit-testing-system/nuts to the plugin list. --- scripts/update-plugin-list.py | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/update-plugin-list.py b/scripts/update-plugin-list.py index eaf561920..f345e1f7c 100644 --- a/scripts/update-plugin-list.py +++ b/scripts/update-plugin-list.py @@ -44,6 +44,7 @@ DEVELOPMENT_STATUS_CLASSIFIERS = ( ) ADDITIONAL_PROJECTS = { # set of additional projects to consider as plugins "logassert", + "nuts", } From 87bfc83aa0d9fbc8f8e95180805a1a58cdf43fd6 Mon Sep 17 00:00:00 2001 From: Tyler Smart Date: Sat, 19 Aug 2023 12:18:17 -0600 Subject: [PATCH 20/34] Add doctesting-coverage to envlist --- tox.ini | 1 + 1 file changed, 1 insertion(+) diff --git a/tox.ini b/tox.ini index 1b62b98e4..c52a43fd7 100644 --- a/tox.ini +++ b/tox.ini @@ -12,6 +12,7 @@ envlist = pypy3 py38-{pexpect,xdist,unittestextras,numpy,pluggymain,pylib} doctesting + doctesting-coverage plugins py38-freeze docs From 3cb3cd1a081dd1bcccedbfdee652e667427fdb87 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sun, 20 Aug 2023 00:16:31 +0300 Subject: [PATCH 21/34] testing: add `.*` to `norecursedirs` Setting `norecursedirs` overrides the default, so we end up scanning dot-directories and such which slows down collection unnecessarily (150ms on my working directory). --- pyproject.toml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index d540773c3..cdbdd3880 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -17,7 +17,12 @@ python_classes = ["Test", "Acceptance"] python_functions = ["test"] # NOTE: "doc" is not included here, but gets tested explicitly via "doctesting". testpaths = ["testing"] -norecursedirs = ["testing/example_scripts"] +norecursedirs = [ + "testing/example_scripts", + ".*", + "build", + "dist", +] xfail_strict = true filterwarnings = [ "error", From 049eec8474d3238b056a42fa07558c4293a97f05 Mon Sep 17 00:00:00 2001 From: Reagan Lee <96998476+reaganjlee@users.noreply.github.com> Date: Sun, 20 Aug 2023 14:04:20 -0700 Subject: [PATCH 22/34] Revert iter raises checks This reverts commit e938580257e8120dabbea789d5b7a3dd3354d0a3. Revert "improve error msg and test" This reverts commit c0cf822ca1d5d6ac74f46ddccbe377c254c6084a. Revert "error msg" This reverts commit ec1053cc162250e42ae220ebe91c3bf00b22b084. Revert "changelog" This reverts commit d2dc8a70b593b61a013ae3eba99bb3f10e82eb65. Revert "simplify code / take out user-gen typeerror case" This reverts commit b9cb87d862bb3f841d67723ac5717ce90b219dc2. --- changelog/7966.bugfix.rst | 1 - src/_pytest/assertion/util.py | 28 +++++++--------------------- testing/test_assertrewrite.py | 4 ++-- 3 files changed, 9 insertions(+), 24 deletions(-) delete mode 100644 changelog/7966.bugfix.rst diff --git a/changelog/7966.bugfix.rst b/changelog/7966.bugfix.rst deleted file mode 100644 index 40cad46c6..000000000 --- a/changelog/7966.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Assertion rewrite mechanism now gives a seperate, more detailed error message from failures within __iter__. diff --git a/src/_pytest/assertion/util.py b/src/_pytest/assertion/util.py index d20c2363e..fc5dfdbd5 100644 --- a/src/_pytest/assertion/util.py +++ b/src/_pytest/assertion/util.py @@ -134,13 +134,6 @@ def isiterable(obj: Any) -> bool: return not istext(obj) except TypeError: return False - except Exception as e: - raise ValueError( - [ - f"pytest_assertion plugin: unexpected exception {e!r} while testing object {obj!r}", - ", probably from __iter__", - ] - ) def has_default_eq( @@ -202,20 +195,13 @@ def assertrepr_compare( explanation = _notin_text(left, right, verbose) except outcomes.Exit: raise - except Exception as e: - if ( - isinstance(e, ValueError) - and (len(e.args) == 1) - and ("__iter__" in str(e.args[0])) - ): - explanation = e.args[0] - else: - explanation = [ - "(pytest_assertion plugin: representation of details failed: {}.".format( - _pytest._code.ExceptionInfo.from_current()._getreprcrash() - ), - " Probably an object has a faulty __repr__.)", - ] + except Exception: + explanation = [ + "(pytest_assertion plugin: representation of details failed: {}.".format( + _pytest._code.ExceptionInfo.from_current()._getreprcrash() + ), + " Probably an object has a faulty __repr__.)", + ] if not explanation: return None diff --git a/testing/test_assertrewrite.py b/testing/test_assertrewrite.py index 62c6bb8d4..d85c8bed6 100644 --- a/testing/test_assertrewrite.py +++ b/testing/test_assertrewrite.py @@ -689,7 +689,7 @@ class TestAssertionRewrite: def f() -> None: class A: def __iter__(self): - raise ValueError() + raise TypeError("user message") def __eq__(self, o: object) -> bool: return self is o @@ -698,7 +698,7 @@ class TestAssertionRewrite: msg = getmsg(f) assert msg is not None - assert "__iter__" in msg and "__repr__" not in msg + assert "Unexpected exception" in msg def test_formatchar(self) -> None: def f() -> None: From 61133ba83d0f24c40aa6b0c1473919c7aff3b16f Mon Sep 17 00:00:00 2001 From: Reagan Lee <96998476+reaganjlee@users.noreply.github.com> Date: Sun, 20 Aug 2023 14:46:09 -0700 Subject: [PATCH 23/34] un-iterable fix --- changelog/7966.bugfix.rst | 1 + src/_pytest/assertion/util.py | 2 +- testing/test_assertrewrite.py | 7 +++++-- 3 files changed, 7 insertions(+), 3 deletions(-) create mode 100644 changelog/7966.bugfix.rst diff --git a/changelog/7966.bugfix.rst b/changelog/7966.bugfix.rst new file mode 100644 index 000000000..de0557680 --- /dev/null +++ b/changelog/7966.bugfix.rst @@ -0,0 +1 @@ +Removes unhelpful error message from assertion rewrite mechanism when exceptions raised in __iter__ methods, and instead treats them as un-iterable. diff --git a/src/_pytest/assertion/util.py b/src/_pytest/assertion/util.py index fc5dfdbd5..39ca5403e 100644 --- a/src/_pytest/assertion/util.py +++ b/src/_pytest/assertion/util.py @@ -132,7 +132,7 @@ def isiterable(obj: Any) -> bool: try: iter(obj) return not istext(obj) - except TypeError: + except Exception: return False diff --git a/testing/test_assertrewrite.py b/testing/test_assertrewrite.py index d85c8bed6..2c908133d 100644 --- a/testing/test_assertrewrite.py +++ b/testing/test_assertrewrite.py @@ -689,16 +689,19 @@ class TestAssertionRewrite: def f() -> None: class A: def __iter__(self): - raise TypeError("user message") + raise ValueError() def __eq__(self, o: object) -> bool: return self is o + def __repr__(self): + return "" + assert A() == A() msg = getmsg(f) assert msg is not None - assert "Unexpected exception" in msg + assert " == " in msg def test_formatchar(self) -> None: def f() -> None: From fc653d0d12fb43aa7fa843cb801d33854e1033b6 Mon Sep 17 00:00:00 2001 From: DetachHead <57028336+DetachHead@users.noreply.github.com> Date: Mon, 21 Aug 2023 18:00:28 +1000 Subject: [PATCH 24/34] use `if not TYPE_CHECKING` on `pytest.__getattr__` to prevent type checkers from using it --- src/pytest/__init__.py | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/pytest/__init__.py b/src/pytest/__init__.py index 831ede1fa..8d7cf520b 100644 --- a/src/pytest/__init__.py +++ b/src/pytest/__init__.py @@ -1,5 +1,7 @@ # PYTHON_ARGCOMPLETE_OK """pytest: unit and functional testing with Python.""" +from typing import TYPE_CHECKING + from _pytest import __version__ from _pytest import version_tuple from _pytest._code import ExceptionInfo @@ -165,11 +167,12 @@ __all__ = [ "yield_fixture", ] +if not TYPE_CHECKING: -def __getattr__(name: str) -> object: - if name == "Instance": - # The import emits a deprecation warning. - from _pytest.python import Instance - - return Instance - raise AttributeError(f"module {__name__} has no attribute {name}") + def __getattr__(name: str) -> object: + if name == "Instance": + # The import emits a deprecation warning. + from _pytest.python import Instance + + return Instance + raise AttributeError(f"module {__name__} has no attribute {name}") From dd5ae0c3b88058c4488fe1411c53e874e79bd7b2 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 21 Aug 2023 08:03:06 +0000 Subject: [PATCH 25/34] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- src/pytest/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pytest/__init__.py b/src/pytest/__init__.py index 8d7cf520b..0aa496a2f 100644 --- a/src/pytest/__init__.py +++ b/src/pytest/__init__.py @@ -173,6 +173,6 @@ if not TYPE_CHECKING: if name == "Instance": # The import emits a deprecation warning. from _pytest.python import Instance - + return Instance raise AttributeError(f"module {__name__} has no attribute {name}") From 010e1742d8f8c1526c417a871d4f82ddf6e5e7de Mon Sep 17 00:00:00 2001 From: DetachHead <57028336+DetachHead@users.noreply.github.com> Date: Mon, 21 Aug 2023 22:29:41 +1000 Subject: [PATCH 26/34] use python 3.11 for update-plugin-list (#11328) --- .github/workflows/update-plugin-list.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/update-plugin-list.yml b/.github/workflows/update-plugin-list.yml index b278f633f..bbce63f7b 100644 --- a/.github/workflows/update-plugin-list.yml +++ b/.github/workflows/update-plugin-list.yml @@ -27,7 +27,7 @@ jobs: - name: Setup Python uses: actions/setup-python@v4 with: - python-version: "3.8" + python-version: "3.11" cache: pip - name: requests-cache uses: actions/cache@v3 From 370eacd3ca8addb5a8eb3f1291feff4304181042 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Mon, 21 Aug 2023 15:40:03 +0300 Subject: [PATCH 27/34] doc/reference: replace Unicode dashes with ascii `-` in cli flags (#11323) --- doc/en/reference/reference.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/en/reference/reference.rst b/doc/en/reference/reference.rst index 5a2458bcb..d578fc285 100644 --- a/doc/en/reference/reference.rst +++ b/doc/en/reference/reference.rst @@ -1640,11 +1640,11 @@ passed multiple times. The expected format is ``name=value``. For example:: Additionally, ``pytest`` will attempt to intelligently identify and ignore a virtualenv by the presence of an activation script. Any directory deemed to be the root of a virtual environment will not be considered during test - collection unless ``‑‑collect‑in‑virtualenv`` is given. Note also that - ``norecursedirs`` takes precedence over ``‑‑collect‑in‑virtualenv``; e.g. if + collection unless ``--collect-in-virtualenv`` is given. Note also that + ``norecursedirs`` takes precedence over ``--collect-in-virtualenv``; e.g. if you intend to run tests in a virtualenv with a base directory that matches ``'.*'`` you *must* override ``norecursedirs`` in addition to using the - ``‑‑collect‑in‑virtualenv`` flag. + ``--collect-in-virtualenv`` flag. .. confval:: python_classes From 4deb38b2edc97e559df067c4d3e4d2b70d2e5f53 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 21 Aug 2023 13:19:58 +0000 Subject: [PATCH 28/34] [automated] Update plugin list (#11329) Co-authored-by: pytest bot --- doc/en/reference/plugin_list.rst | 440 +++++++++++++++++++++---------- 1 file changed, 308 insertions(+), 132 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index 0a333976e..9d5728352 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -15,7 +15,7 @@ Packages classified as inactive are excluded. creating a PDF, because otherwise the table gets far too wide for the page. -This list contains 1289 plugins. +This list contains 1311 plugins. .. only:: not latex @@ -23,10 +23,12 @@ This list contains 1289 plugins. name summary last release status requires =============================================== ======================================================================================================================================================================================================== ============== ===================== ================================================ :pypi:`logassert` Simple but powerful assertion and verification of logged lines. May 20, 2022 5 - Production/Stable N/A + :pypi:`nuts` Network Unit Testing System Aug 11, 2023 N/A pytest (>=7.3.0,<8.0.0) :pypi:`pytest-abq` Pytest integration for the ABQ universal test runner. Apr 07, 2023 N/A N/A :pypi:`pytest-abstracts` A contextmanager pytest fixture for handling multiple mock abstracts May 25, 2022 N/A N/A :pypi:`pytest-accept` A pytest-plugin for updating doctest outputs Dec 21, 2022 N/A pytest (>=6,<8) :pypi:`pytest-adaptavist` pytest plugin for generating test execution results within Jira Test Management (tm4j) Oct 13, 2022 N/A pytest (>=5.4.0) + :pypi:`pytest-adaptavist-fixed` pytest plugin for generating test execution results within Jira Test Management (tm4j) Aug 15, 2023 N/A N/A :pypi:`pytest-addons-test` 用于测试pytest的插件 Aug 02, 2021 N/A pytest (>=6.2.4,<7.0.0) :pypi:`pytest-adf` Pytest plugin for writing Azure Data Factory integration tests May 10, 2021 4 - Beta pytest (>=3.5.0) :pypi:`pytest-adf-azure-identity` Pytest plugin for writing Azure Data Factory integration tests Mar 06, 2021 4 - Beta pytest (>=3.5.0) @@ -52,10 +54,11 @@ This list contains 1289 plugins. :pypi:`pytest-allure-intersection` Oct 27, 2022 N/A pytest (<5) :pypi:`pytest-allure-spec-coverage` The pytest plugin aimed to display test coverage of the specs(requirements) in Allure Oct 26, 2021 N/A pytest :pypi:`pytest-alphamoon` Static code checks used at Alphamoon Dec 30, 2021 5 - Production/Stable pytest (>=3.5.0) + :pypi:`pytest-analyzer` this plugin allows to analyze tests in pytest project, collect test metadata and sync it with testomat.io TCM system Aug 21, 2023 N/A pytest >=7.3.1 :pypi:`pytest-android` This fixture provides a configured "driver" for Android Automated Testing, using uiautomator2. Feb 21, 2019 3 - Alpha pytest :pypi:`pytest-anki` A pytest plugin for testing Anki add-ons Jul 31, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-annotate` pytest-annotate: Generate PyAnnotate annotations from your pytest tests. Jun 07, 2022 3 - Alpha pytest (<8.0.0,>=3.2.0) - :pypi:`pytest-ansible` Plugin for pytest to simplify calling ansible modules from tests or fixtures May 15, 2023 5 - Production/Stable pytest (<8.0.0,>=6) + :pypi:`pytest-ansible` Plugin for pytest to simplify calling ansible modules from tests or fixtures Aug 09, 2023 5 - Production/Stable pytest <8.0.0,>=6 :pypi:`pytest-ansible-playbook` Pytest fixture which runs given ansible playbook file. Mar 08, 2019 4 - Beta N/A :pypi:`pytest-ansible-playbook-runner` Pytest fixture which runs given ansible playbook file. Dec 02, 2020 4 - Beta pytest (>=3.1.0) :pypi:`pytest-ansible-units` A pytest plugin for running unit tests within an ansible collection Apr 14, 2022 N/A N/A @@ -89,7 +92,7 @@ This list contains 1289 plugins. :pypi:`pytest-ast-transformer` May 04, 2019 3 - Alpha pytest :pypi:`pytest-async-generators` Pytest fixtures for async generators Jul 05, 2023 N/A N/A :pypi:`pytest-asyncio` Pytest support for asyncio Jul 12, 2023 4 - Beta pytest (>=7.0.0) - :pypi:`pytest-asyncio-cooperative` Run all your asynchronous tests cooperatively. May 31, 2023 N/A N/A + :pypi:`pytest-asyncio-cooperative` Run all your asynchronous tests cooperatively. Aug 06, 2023 N/A N/A :pypi:`pytest-asyncio-network-simulator` pytest-asyncio-network-simulator: Plugin for pytest for simulator the network in tests Jul 31, 2018 3 - Alpha pytest (<3.7.0,>=3.3.2) :pypi:`pytest-async-mongodb` pytest plugin for async MongoDB Oct 18, 2017 5 - Production/Stable pytest (>=2.5.2) :pypi:`pytest-async-sqlalchemy` Database testing fixtures using the SQLAlchemy asyncio API Oct 07, 2021 4 - Beta pytest (>=6.0.0) @@ -107,6 +110,7 @@ This list contains 1289 plugins. :pypi:`pytest-aws` pytest plugin for testing AWS resource configurations Oct 04, 2017 4 - Beta N/A :pypi:`pytest-aws-config` Protect your AWS credentials in unit tests May 28, 2021 N/A N/A :pypi:`pytest-axe` pytest plugin for axe-selenium-python Nov 12, 2018 N/A pytest (>=3.0.0) + :pypi:`pytest-axe-playwright-snapshot` A pytest plugin that runs Axe-core on Playwright pages and takes snapshots of the results. Jul 25, 2023 N/A pytest :pypi:`pytest-azure` Pytest utilities and mocks for Azure Jan 18, 2023 3 - Alpha pytest :pypi:`pytest-azure-devops` Simplifies using azure devops parallel strategy (https://docs.microsoft.com/en-us/azure/devops/pipelines/test/parallel-testing-any-test-runner) with pytest. Jun 20, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-azurepipelines` Formatting PyTest output for Azure Pipelines UI Oct 20, 2022 5 - Production/Stable pytest (>=5.0.0) @@ -116,6 +120,7 @@ This list contains 1289 plugins. :pypi:`pytest-bdd` BDD for pytest Nov 08, 2022 6 - Mature pytest (>=6.2.0) :pypi:`pytest-bdd-html` pytest plugin to display BDD info in HTML test report Nov 22, 2022 3 - Alpha pytest (!=6.0.0,>=5.0) :pypi:`pytest-bdd-ng` BDD for pytest Jul 01, 2023 4 - Beta pytest (>=5.0) + :pypi:`pytest-bdd-report` A pytest-bdd plugin for generating useful and informative BDD test reports Aug 20, 2023 N/A N/A :pypi:`pytest-bdd-splinter` Common steps for pytest bdd and splinter integration Aug 12, 2019 5 - Production/Stable pytest (>=4.0.0) :pypi:`pytest-bdd-web` A simple plugin to use with pytest Jan 02, 2020 4 - Beta pytest (>=3.5.0) :pypi:`pytest-bdd-wrappers` Feb 11, 2020 2 - Pre-Alpha N/A @@ -132,7 +137,7 @@ This list contains 1289 plugins. :pypi:`pytest-black-multipy` Allow '--black' on older Pythons Jan 14, 2021 5 - Production/Stable pytest (!=3.7.3,>=3.5) ; extra == 'testing' :pypi:`pytest-black-ng` A pytest plugin to enable format checking with black Oct 20, 2022 4 - Beta pytest (>=7.0.0) :pypi:`pytest-blame` A pytest plugin helps developers to debug by providing useful commits history. May 04, 2019 N/A pytest (>=4.4.0) - :pypi:`pytest-blender` Blender Pytest plugin. Jan 04, 2023 N/A pytest ; extra == 'dev' + :pypi:`pytest-blender` Blender Pytest plugin. Aug 10, 2023 N/A pytest ; extra == 'dev' :pypi:`pytest-blink1` Pytest plugin to emit notifications via the Blink(1) RGB LED Jan 07, 2018 4 - Beta N/A :pypi:`pytest-blockage` Disable network requests during a test run. Dec 21, 2021 N/A pytest :pypi:`pytest-blocker` pytest plugin to mark a test as blocker and skip all other tests Sep 07, 2015 4 - Beta N/A @@ -157,7 +162,7 @@ This list contains 1289 plugins. :pypi:`pytest-builtin-types` Nov 17, 2021 N/A pytest :pypi:`pytest-bwrap` Run your tests in Bubblewrap sandboxes Oct 26, 2018 3 - Alpha N/A :pypi:`pytest-cache` pytest plugin with mechanisms for caching across test runs Jun 04, 2013 3 - Alpha N/A - :pypi:`pytest-cache-assert` Cache assertion data to simplify regression testing of complex serializable data Feb 26, 2023 5 - Production/Stable pytest (>=5.0.0) + :pypi:`pytest-cache-assert` Cache assertion data to simplify regression testing of complex serializable data Aug 14, 2023 5 - Production/Stable pytest (>=6.0.0) :pypi:`pytest-cagoule` Pytest plugin to only run tests affected by changes Jan 01, 2020 3 - Alpha N/A :pypi:`pytest-cairo` Pytest support for cairo-lang and starknet Apr 17, 2022 N/A pytest :pypi:`pytest-call-checker` Small pytest utility to easily create test doubles Oct 16, 2022 4 - Beta pytest (>=7.1.3,<8.0.0) @@ -178,8 +183,8 @@ This list contains 1289 plugins. :pypi:`pytest-change-report` turn . into √,turn F into x Sep 14, 2020 N/A pytest :pypi:`pytest-change-xds` turn . into √,turn F into x Apr 16, 2022 N/A pytest :pypi:`pytest-chdir` A pytest fixture for changing current working directory Jan 28, 2020 N/A pytest (>=5.0.0,<6.0.0) - :pypi:`pytest-check` A pytest plugin that allows multiple failures per test. Jul 14, 2023 N/A pytest - :pypi:`pytest-checkdocs` check the README when running tests Jul 09, 2023 5 - Production/Stable pytest (>=6) ; extra == 'testing' + :pypi:`pytest-check` A pytest plugin that allows multiple failures per test. Aug 11, 2023 N/A pytest + :pypi:`pytest-checkdocs` check the README when running tests Jul 30, 2023 5 - Production/Stable pytest (>=6) ; extra == 'testing' :pypi:`pytest-checkipdb` plugin to check if there are ipdb debugs left Jul 22, 2020 5 - Production/Stable pytest (>=2.9.2) :pypi:`pytest-check-library` check your missing library Jul 17, 2022 N/A N/A :pypi:`pytest-check-libs` check your missing library Jul 17, 2022 N/A N/A @@ -209,7 +214,8 @@ This list contains 1289 plugins. :pypi:`pytest-codegen` Automatically create pytest test signatures Aug 23, 2020 2 - Pre-Alpha N/A :pypi:`pytest-codeowners` Pytest plugin for selecting tests by GitHub CODEOWNERS. Mar 30, 2022 4 - Beta pytest (>=6.0.0) :pypi:`pytest-codestyle` pytest plugin to run pycodestyle Mar 23, 2020 3 - Alpha N/A - :pypi:`pytest-codspeed` Pytest plugin to create CodSpeed benchmarks Jul 04, 2023 5 - Production/Stable pytest>=3.8 + :pypi:`pytest-codspeed` Pytest plugin to create CodSpeed benchmarks Jul 27, 2023 5 - Production/Stable pytest>=3.8 + :pypi:`pytest-collect-appoint-info` set your encoding Aug 03, 2023 N/A pytest :pypi:`pytest-collect-formatter` Formatter for pytest collect output Mar 29, 2021 5 - Production/Stable N/A :pypi:`pytest-collect-formatter2` Formatter for pytest collect output May 31, 2021 5 - Production/Stable N/A :pypi:`pytest-collector` Python package for collecting pytest. Aug 02, 2022 N/A pytest (>=7.0,<8.0) @@ -279,10 +285,12 @@ This list contains 1289 plugins. :pypi:`pytest-dbt` Unit test dbt models with standard python tooling Jun 08, 2023 2 - Pre-Alpha pytest (>=7.0.0,<8.0.0) :pypi:`pytest-dbt-adapter` A pytest plugin for testing dbt adapter plugins Nov 24, 2021 N/A pytest (<7,>=6) :pypi:`pytest-dbt-conventions` A pytest plugin for linting a dbt project's conventions Mar 02, 2022 N/A pytest (>=6.2.5,<7.0.0) - :pypi:`pytest-dbt-core` Pytest extension for dbt. May 03, 2023 N/A pytest (>=6.2.5) ; extra == 'test' + :pypi:`pytest-dbt-core` Pytest extension for dbt. Aug 09, 2023 N/A pytest >=6.2.5 ; extra == 'test' :pypi:`pytest-dbus-notification` D-BUS notifications for pytest results. Mar 05, 2014 5 - Production/Stable N/A :pypi:`pytest-dbx` Pytest plugin to run unit tests for dbx (Databricks CLI extensions) related code Nov 29, 2022 N/A pytest (>=7.1.3,<8.0.0) + :pypi:`pytest-dc` Manages Docker containers during your integration tests Aug 16, 2023 5 - Production/Stable pytest >=3.3 :pypi:`pytest-deadfixtures` A simple plugin to list unused fixtures in pytest Jul 23, 2020 5 - Production/Stable N/A + :pypi:`pytest-deduplicate` Identifies duplicate unit tests Aug 12, 2023 4 - Beta pytest :pypi:`pytest-deepcov` deepcov Mar 30, 2021 N/A N/A :pypi:`pytest-defer` Aug 24, 2021 N/A N/A :pypi:`pytest-demo-plugin` pytest示例插件 May 15, 2021 N/A N/A @@ -309,6 +317,7 @@ This list contains 1289 plugins. :pypi:`pytest-djangoapp` Nice pytest plugin to help you with Django pluggable application testing. May 19, 2023 4 - Beta pytest :pypi:`pytest-django-cache-xdist` A djangocachexdist plugin for pytest May 12, 2020 4 - Beta N/A :pypi:`pytest-django-casperjs` Integrate CasperJS with your django tests as a pytest fixture. Mar 15, 2015 2 - Pre-Alpha N/A + :pypi:`pytest-django-class` A pytest plugin for running django in class-scoped fixtures Aug 08, 2023 4 - Beta N/A :pypi:`pytest-django-dotenv` Pytest plugin used to setup environment variables with django-dotenv Nov 26, 2019 4 - Beta pytest (>=2.6.0) :pypi:`pytest-django-factories` Factories for your Django models that can be used as Pytest fixtures. Nov 12, 2020 4 - Beta N/A :pypi:`pytest-django-filefield` Replaces FileField.storage with something you can patch globally. May 09, 2022 5 - Production/Stable pytest >= 5.2 @@ -348,8 +357,9 @@ This list contains 1289 plugins. :pypi:`pytest-doctest-custom` A py.test plugin for customizing string representations of doctest results. Jul 25, 2016 4 - Beta N/A :pypi:`pytest-doctest-ellipsis-markers` Setup additional values for ELLIPSIS_MARKER for doctests Jan 12, 2018 4 - Beta N/A :pypi:`pytest-doctest-import` A simple pytest plugin to import names and add them to the doctest namespace. Nov 13, 2018 4 - Beta pytest (>=3.3.0) - :pypi:`pytest-doctestplus` Pytest plugin with advanced doctest features. Jun 08, 2023 3 - Alpha pytest (>=4.6) + :pypi:`pytest-doctestplus` Pytest plugin with advanced doctest features. Aug 11, 2023 3 - Alpha pytest >=4.6 :pypi:`pytest-dogu-report` pytest plugin for dogu report Jul 07, 2023 N/A N/A + :pypi:`pytest-dogu-sdk` pytest plugin for the Dogu Aug 04, 2023 N/A N/A :pypi:`pytest-dolphin` Some extra stuff that we use ininternally Nov 30, 2016 4 - Beta pytest (==3.0.4) :pypi:`pytest-doorstop` A pytest plugin for adding test results into doorstop items. Jun 09, 2020 4 - Beta pytest (>=3.5.0) :pypi:`pytest-dotenv` A py.test plugin that parses environment files before running tests Jun 16, 2020 4 - Beta pytest (>=5.0.0) @@ -373,7 +383,7 @@ This list contains 1289 plugins. :pypi:`pytest-ec2` Pytest execution on EC2 instance Oct 22, 2019 3 - Alpha N/A :pypi:`pytest-echo` pytest plugin with mechanisms for echoing environment variables, package version and generic attributes Jan 08, 2020 5 - Production/Stable N/A :pypi:`pytest-ekstazi` Pytest plugin to select test using Ekstazi algorithm Sep 10, 2022 N/A pytest - :pypi:`pytest-elasticsearch` Elasticsearch fixtures and fixture factories for Pytest. Mar 01, 2022 5 - Production/Stable pytest (>=6.2.0) + :pypi:`pytest-elasticsearch` Elasticsearch fixtures and fixture factories for Pytest. Aug 03, 2023 5 - Production/Stable pytest (>=6.2) :pypi:`pytest-elements` Tool to help automate user interfaces Jan 13, 2021 N/A pytest (>=5.4,<6.0) :pypi:`pytest-eliot` An eliot plugin for pytest. Aug 31, 2022 1 - Planning pytest (>=5.4.0) :pypi:`pytest-elk-reporter` A simple plugin to use with pytest Jan 24, 2021 4 - Beta pytest (>=3.5.0) @@ -391,6 +401,7 @@ This list contains 1289 plugins. :pypi:`pytest-enabler` Enable installed pytest plugins Jul 14, 2023 5 - Production/Stable pytest (>=6) ; extra == 'testing' :pypi:`pytest-encode` set your encoding and logger Nov 06, 2021 N/A N/A :pypi:`pytest-encode-kane` set your encoding and logger Nov 16, 2021 N/A pytest + :pypi:`pytest-encoding` set your encoding and logger Aug 11, 2023 N/A pytest :pypi:`pytest-enhanced-reports` Enhanced test reports for pytest Dec 15, 2022 N/A N/A :pypi:`pytest-enhancements` Improvements for pytest (rejected upstream) Oct 30, 2019 4 - Beta N/A :pypi:`pytest-env` py.test plugin that allows you to add environment variables. Jun 15, 2023 5 - Production/Stable pytest>=7.3.1 @@ -406,7 +417,7 @@ This list contains 1289 plugins. :pypi:`pytest-eucalyptus` Pytest Plugin for BDD Jun 28, 2022 N/A pytest (>=4.2.0) :pypi:`pytest-eventlet` Applies eventlet monkey-patch as a pytest plugin. Oct 04, 2021 N/A pytest ; extra == 'dev' :pypi:`pytest-examples` Pytest plugin for testing examples in docstrings and markdown files. Jul 11, 2023 4 - Beta pytest>=7 - :pypi:`pytest-excel` pytest plugin for generating excel reports Jan 31, 2022 5 - Production/Stable N/A + :pypi:`pytest-excel` pytest plugin for generating excel reports Jul 20, 2023 5 - Production/Stable N/A :pypi:`pytest-exceptional` Better exceptions Mar 16, 2017 4 - Beta N/A :pypi:`pytest-exception-script` Walk your code through exception script to check it's resiliency to failures. Aug 04, 2020 3 - Alpha pytest :pypi:`pytest-executable` pytest plugin for testing executables Mar 25, 2023 N/A pytest (<8,>=4.3) @@ -418,7 +429,8 @@ This list contains 1289 plugins. :pypi:`pytest-expect-test` A fixture to support expect tests in pytest Apr 10, 2023 4 - Beta pytest (>=3.5.0) :pypi:`pytest-experiments` A pytest plugin to help developers of research-oriented software projects keep track of the results of their numerical experiments. Dec 13, 2021 4 - Beta pytest (>=6.2.5,<7.0.0) :pypi:`pytest-explicit` A Pytest plugin to ignore certain marked tests by default Jun 15, 2021 5 - Production/Stable pytest - :pypi:`pytest-exploratory` Interactive console for pytest. Feb 21, 2022 N/A pytest (>=6.2) + :pypi:`pytest-exploratory` Interactive console for pytest. Aug 18, 2023 N/A pytest (>=6.2) + :pypi:`pytest-explorer` terminal ui for exploring and running tests Aug 01, 2023 N/A N/A :pypi:`pytest-extensions` A collection of helpers for pytest to ease testing Aug 17, 2022 4 - Beta pytest ; extra == 'testing' :pypi:`pytest-external-blockers` a special outcome for tests that are blocked for external reasons Oct 05, 2021 N/A pytest :pypi:`pytest-extra-durations` A pytest plugin to get durations on a per-function basis and per module basis. Apr 21, 2020 4 - Beta pytest (>=3.5.0) @@ -482,7 +494,7 @@ This list contains 1289 plugins. :pypi:`pytest-forcefail` py.test plugin to make the test failing regardless of pytest.mark.xfail May 15, 2018 4 - Beta N/A :pypi:`pytest-forward-compatability` A name to avoid typosquating pytest-foward-compatibility Sep 06, 2020 N/A N/A :pypi:`pytest-forward-compatibility` A pytest plugin to shim pytest commandline options for fowards compatibility Sep 29, 2020 N/A N/A - :pypi:`pytest-frappe` Pytest Frappe Plugin - A set of pytest fixtures to test Frappe applications May 03, 2023 4 - Beta pytest>=7.0.0 + :pypi:`pytest-frappe` Pytest Frappe Plugin - A set of pytest fixtures to test Frappe applications Aug 07, 2023 4 - Beta pytest>=7.0.0 :pypi:`pytest-freezegun` Wrap tests with fixtures in freeze_time Jul 19, 2020 4 - Beta pytest (>=3.0.0) :pypi:`pytest-freezer` Pytest plugin providing a fixture interface for spulec/freezegun Jun 21, 2023 N/A pytest >= 3.6 :pypi:`pytest-freeze-reqs` Check if requirement files are frozen Apr 29, 2021 N/A N/A @@ -499,7 +511,7 @@ This list contains 1289 plugins. :pypi:`pytest-gherkin` A flexible framework for executing BDD gherkin tests Jul 27, 2019 3 - Alpha pytest (>=5.0.0) :pypi:`pytest-gh-log-group` pytest plugin for gh actions Jan 11, 2022 3 - Alpha pytest :pypi:`pytest-ghostinspector` For finding/executing Ghost Inspector tests May 17, 2016 3 - Alpha N/A - :pypi:`pytest-girder` A set of pytest fixtures for testing Girder applications. Jun 28, 2023 N/A N/A + :pypi:`pytest-girder` A set of pytest fixtures for testing Girder applications. Jul 24, 2023 N/A N/A :pypi:`pytest-git` Git repository fixture for py.test May 28, 2019 5 - Production/Stable pytest :pypi:`pytest-gitconfig` Provide a gitconfig sandbox for testing Jun 22, 2023 4 - Beta pytest>=7.1.2 :pypi:`pytest-gitcov` Pytest plugin for reporting on coverage of the last git commit. Jan 11, 2020 2 - Pre-Alpha N/A @@ -533,7 +545,7 @@ This list contains 1289 plugins. :pypi:`pytest-historic` Custom report to display pytest historical execution records Apr 08, 2020 N/A pytest :pypi:`pytest-historic-hook` Custom listener to store execution results into MYSQL DB, which is used for pytest-historic report Apr 08, 2020 N/A pytest :pypi:`pytest-homeassistant` A pytest plugin for use with homeassistant custom components. Aug 12, 2020 4 - Beta N/A - :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components Jul 14, 2023 3 - Alpha pytest (==7.3.1) + :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components Aug 19, 2023 3 - Alpha pytest ==7.3.1 :pypi:`pytest-honey` A simple plugin to use with pytest Jan 07, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-honors` Report on tests that honor constraints, and guard against regressions Mar 06, 2020 4 - Beta N/A :pypi:`pytest-hot-reloading` Jun 23, 2023 N/A N/A @@ -541,7 +553,8 @@ This list contains 1289 plugins. :pypi:`pytest-hoverfly` Simplify working with Hoverfly from pytest Jan 30, 2023 N/A pytest (>=5.0) :pypi:`pytest-hoverfly-wrapper` Integrates the Hoverfly HTTP proxy into Pytest Feb 27, 2023 5 - Production/Stable pytest (>=3.7.0) :pypi:`pytest-hpfeeds` Helpers for testing hpfeeds in your python project Feb 28, 2023 4 - Beta pytest (>=6.2.4,<7.0.0) - :pypi:`pytest-html` pytest plugin for generating HTML reports Apr 08, 2023 5 - Production/Stable pytest (!=6.0.0,>=5.0) + :pypi:`pytest-html` pytest plugin for generating HTML reports Aug 13, 2023 5 - Production/Stable pytest (!=6.0.0,>=5.0) + :pypi:`pytest-html-cn` pytest plugin for generating HTML reports Aug 01, 2023 5 - Production/Stable N/A :pypi:`pytest-html-lee` optimized pytest plugin for generating HTML reports Jun 30, 2020 5 - Production/Stable pytest (>=5.0) :pypi:`pytest-html-merger` Pytest HTML reports merging utility Apr 03, 2022 N/A N/A :pypi:`pytest-html-object-storage` Pytest report plugin for send HTML report on object-storage Mar 04, 2022 5 - Production/Stable N/A @@ -555,18 +568,20 @@ This list contains 1289 plugins. :pypi:`pytest-http-mocker` Pytest plugin for http mocking (via https://github.com/vilus/mocker) Oct 20, 2019 N/A N/A :pypi:`pytest-httpretty` A thin wrapper of HTTPretty for pytest Feb 16, 2014 3 - Alpha N/A :pypi:`pytest-httpserver` pytest-httpserver is a httpserver for pytest May 22, 2023 3 - Alpha N/A - :pypi:`pytest-httptesting` http_testing framework on top of pytest Jul 09, 2023 N/A pytest (>=7.2.0,<8.0.0) - :pypi:`pytest-httpx` Send responses to httpx. Apr 12, 2023 5 - Production/Stable pytest (<8.0,>=6.0) + :pypi:`pytest-httptesting` http_testing framework on top of pytest Jul 24, 2023 N/A pytest (>=7.2.0,<8.0.0) + :pypi:`pytest-httpx` Send responses to httpx. Aug 02, 2023 5 - Production/Stable pytest (<8.0,>=6.0) :pypi:`pytest-httpx-blockage` Disable httpx requests during a test run Feb 16, 2023 N/A pytest (>=7.2.1) :pypi:`pytest-hue` Visualise PyTest status via your Phillips Hue lights May 09, 2019 N/A N/A :pypi:`pytest-hylang` Pytest plugin to allow running tests written in hylang Mar 28, 2021 N/A pytest :pypi:`pytest-hypo-25` help hypo module for pytest Jan 12, 2020 3 - Alpha N/A + :pypi:`pytest-iam` A fully functional OAUTH2 / OpenID Connect (OIDC) server to be used in your testsuite Aug 21, 2023 3 - Alpha pytest (>=7.0.0,<8.0.0) :pypi:`pytest-ibutsu` A plugin to sent pytest results to an Ibutsu server Aug 05, 2022 4 - Beta pytest>=7.1 :pypi:`pytest-icdiff` use icdiff for better error messages in pytest assertions Aug 09, 2022 4 - Beta N/A :pypi:`pytest-idapro` A pytest plugin for idapython. Allows a pytest setup to run tests outside and inside IDA in an automated manner by runnig pytest inside IDA and by mocking idapython api Nov 03, 2018 N/A N/A :pypi:`pytest-idem` A pytest plugin to help with testing idem projects Jun 23, 2023 5 - Production/Stable N/A :pypi:`pytest-idempotent` Pytest plugin for testing function idempotence. Jul 25, 2022 N/A N/A :pypi:`pytest-ignore-flaky` ignore failures from flaky tests (pytest plugin) Apr 23, 2021 5 - Production/Stable N/A + :pypi:`pytest-ignore-test-results` A pytest plugin to ignore test results. Aug 17, 2023 2 - Pre-Alpha pytest>=7.0 :pypi:`pytest-image-diff` Mar 09, 2023 3 - Alpha pytest :pypi:`pytest-incremental` an incremental test runner (pytest plugin) Apr 24, 2021 5 - Production/Stable N/A :pypi:`pytest-influxdb` Plugin for influxdb and pytest integration. Apr 20, 2021 N/A N/A @@ -575,7 +590,7 @@ This list contains 1289 plugins. :pypi:`pytest-infrastructure` pytest stack validation prior to testing executing Apr 12, 2020 4 - Beta N/A :pypi:`pytest-ini` Reuse pytest.ini to store env variables Apr 26, 2022 N/A N/A :pypi:`pytest-inline` A pytest plugin for writing inline tests. Feb 08, 2023 4 - Beta pytest (>=7.0.0) - :pypi:`pytest-inmanta` A py.test plugin providing fixtures to simplify inmanta modules testing. Feb 23, 2023 5 - Production/Stable N/A + :pypi:`pytest-inmanta` A py.test plugin providing fixtures to simplify inmanta modules testing. Aug 03, 2023 5 - Production/Stable N/A :pypi:`pytest-inmanta-extensions` Inmanta tests package Jul 04, 2023 5 - Production/Stable N/A :pypi:`pytest-inmanta-lsm` Common fixtures for inmanta LSM related modules May 17, 2023 5 - Production/Stable N/A :pypi:`pytest-inmanta-yang` Common fixtures used in inmanta yang related modules Jun 16, 2022 4 - Beta N/A @@ -645,17 +660,18 @@ This list contains 1289 plugins. :pypi:`pytest-libnotify` Pytest plugin that shows notifications about the test run Apr 02, 2021 3 - Alpha pytest :pypi:`pytest-ligo` Jan 16, 2020 4 - Beta N/A :pypi:`pytest-lineno` A pytest plugin to show the line numbers of test functions Dec 04, 2020 N/A pytest - :pypi:`pytest-line-profiler` Profile code executed by pytest May 03, 2021 4 - Beta pytest (>=3.5.0) + :pypi:`pytest-line-profiler` Profile code executed by pytest Aug 10, 2023 4 - Beta pytest >=3.5.0 :pypi:`pytest-line-profiler-apn` Profile code executed by pytest Dec 05, 2022 N/A pytest (>=3.5.0) :pypi:`pytest-lisa` Pytest plugin for organizing tests. Jan 21, 2021 3 - Alpha pytest (>=6.1.2,<7.0.0) :pypi:`pytest-listener` A simple network listener May 28, 2019 5 - Production/Stable pytest :pypi:`pytest-litf` A pytest plugin that stream output in LITF format Jan 18, 2021 4 - Beta pytest (>=3.1.1) + :pypi:`pytest-litter` Pytest plugin which verifies that tests do not modify file trees. Aug 08, 2023 4 - Beta pytest >=6.1 :pypi:`pytest-live` Live results for pytest Mar 08, 2020 N/A pytest :pypi:`pytest-local-badge` Generate local badges (shields) reporting your test suite status. Jan 15, 2023 N/A pytest (>=6.1.0) :pypi:`pytest-localftpserver` A PyTest plugin which provides an FTP fixture for your tests Oct 04, 2022 5 - Production/Stable pytest :pypi:`pytest-localserver` pytest plugin to test server connections locally. Jul 16, 2023 4 - Beta N/A :pypi:`pytest-localstack` Pytest plugin for AWS integration tests Jun 07, 2023 4 - Beta pytest (>=6.0.0,<7.0.0) - :pypi:`pytest-lockable` lockable resource plugin for pytest Jul 20, 2022 5 - Production/Stable pytest + :pypi:`pytest-lockable` lockable resource plugin for pytest Aug 09, 2023 5 - Production/Stable pytest :pypi:`pytest-locker` Used to lock object during testing. Essentially changing assertions from being hard coded to asserting that nothing changed Oct 29, 2021 N/A pytest (>=5.4) :pypi:`pytest-log` print log Aug 15, 2021 N/A pytest (>=3.8) :pypi:`pytest-logbook` py.test plugin to capture logbook log messages Nov 23, 2015 5 - Production/Stable pytest (>=2.8) @@ -710,7 +726,7 @@ This list contains 1289 plugins. :pypi:`pytest-mock-helper` Help you mock HTTP call and generate mock code Jan 24, 2018 N/A pytest :pypi:`pytest-mockito` Base fixtures for mockito Jul 11, 2018 4 - Beta N/A :pypi:`pytest-mockredis` An in-memory mock of a Redis server that runs in a separate thread. This is to be used for unit-tests that require a Redis database. Jan 02, 2018 2 - Pre-Alpha N/A - :pypi:`pytest-mock-resources` A pytest plugin for easily instantiating reproducible mock resources. Jul 12, 2023 N/A pytest (>=1.0) + :pypi:`pytest-mock-resources` A pytest plugin for easily instantiating reproducible mock resources. Jul 24, 2023 N/A pytest (>=1.0) :pypi:`pytest-mock-server` Mock server plugin for pytest Jan 09, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-mockservers` A set of fixtures to test your requests to HTTP/UDP servers Mar 31, 2020 N/A pytest (>=4.3.0) :pypi:`pytest-mocktcp` A pytest plugin for testing TCP clients Oct 11, 2022 N/A pytest @@ -719,7 +735,7 @@ This list contains 1289 plugins. :pypi:`pytest-modifyscope` pytest plugin to modify fixture scope Apr 12, 2020 N/A pytest :pypi:`pytest-molecule` PyTest Molecule Plugin :: discover and run molecule tests Mar 29, 2022 5 - Production/Stable pytest (>=7.0.0) :pypi:`pytest-molecule-JC` PyTest Molecule Plugin :: discover and run molecule tests Jul 18, 2023 5 - Production/Stable pytest (>=7.0.0) - :pypi:`pytest-mongo` MongoDB process and client fixtures plugin for Pytest. Jun 07, 2021 5 - Production/Stable pytest + :pypi:`pytest-mongo` MongoDB process and client fixtures plugin for Pytest. Jul 20, 2023 5 - Production/Stable pytest (>=6.2) :pypi:`pytest-mongodb` pytest plugin for MongoDB fixtures May 16, 2023 5 - Production/Stable N/A :pypi:`pytest-monitor` Pytest plugin for analyzing resource usage. Jun 25, 2023 5 - Production/Stable pytest :pypi:`pytest-monkeyplus` pytest's monkeypatch subclass with extra functionalities Sep 18, 2012 5 - Production/Stable N/A @@ -731,7 +747,7 @@ This list contains 1289 plugins. :pypi:`pytest-mpiexec` pytest plugin for running individual tests with mpiexec Apr 13, 2023 3 - Alpha pytest :pypi:`pytest-mpl` pytest plugin to help with testing figures output from Matplotlib Jul 23, 2022 4 - Beta pytest :pypi:`pytest-mproc` low-startup-overhead, scalable, distributed-testing pytest plugin Nov 15, 2022 4 - Beta pytest (>=6) - :pypi:`pytest-mqtt` pytest-mqtt supports testing systems based on MQTT Mar 15, 2023 4 - Beta pytest (<8) ; extra == 'test' + :pypi:`pytest-mqtt` pytest-mqtt supports testing systems based on MQTT Aug 03, 2023 4 - Beta pytest (<8) ; extra == 'test' :pypi:`pytest-multihost` Utility for writing multi-host tests for pytest Apr 07, 2020 4 - Beta N/A :pypi:`pytest-multilog` Multi-process logs handling and other helpers for pytest Jan 17, 2023 N/A pytest :pypi:`pytest-multithreading` a pytest plugin for th and concurrent testing Dec 07, 2022 N/A N/A @@ -739,7 +755,7 @@ This list contains 1289 plugins. :pypi:`pytest-mutagen` Add the mutation testing feature to pytest Jul 24, 2020 N/A pytest (>=5.4) :pypi:`pytest-mypy` Mypy static type checker plugin for Pytest Dec 18, 2022 4 - Beta pytest (>=6.2) ; python_version >= "3.10" :pypi:`pytest-mypyd` Mypy static type checker plugin for Pytest Aug 20, 2019 4 - Beta pytest (<4.7,>=2.8) ; python_version < "3.5" - :pypi:`pytest-mypy-plugins` pytest plugin for writing tests for mypy plugins Jun 29, 2023 4 - Beta pytest (>=7.0.0) + :pypi:`pytest-mypy-plugins` pytest plugin for writing tests for mypy plugins Jul 25, 2023 4 - Beta pytest (>=7.0.0) :pypi:`pytest-mypy-plugins-shim` Substitute for "pytest-mypy-plugins" for Python implementations which aren't supported by mypy. Apr 12, 2021 N/A pytest>=6.0.0 :pypi:`pytest-mypy-testing` Pytest plugin to check mypy output. Feb 25, 2023 N/A pytest>=7,<8 :pypi:`pytest-mysql` MySQL process and client fixtures for pytest Mar 27, 2023 5 - Production/Stable pytest (>=6.2) @@ -754,13 +770,14 @@ This list contains 1289 plugins. :pypi:`pytest-nginx-iplweb` nginx fixture for pytest - iplweb temporary fork Mar 01, 2019 5 - Production/Stable N/A :pypi:`pytest-ngrok` Jan 20, 2022 3 - Alpha pytest :pypi:`pytest-ngsfixtures` pytest ngs fixtures Sep 06, 2019 2 - Pre-Alpha pytest (>=5.0.0) - :pypi:`pytest-nhsd-apim` Pytest plugin accessing NHSDigital's APIM proxies Jul 11, 2023 N/A pytest (==6.2.5) + :pypi:`pytest-nhsd-apim` Pytest plugin accessing NHSDigital's APIM proxies Aug 02, 2023 N/A pytest (==6.2.5) :pypi:`pytest-nice` A pytest plugin that alerts user of failed test cases with screen notifications May 04, 2019 4 - Beta pytest :pypi:`pytest-nice-parametrize` A small snippet for nicer PyTest's Parametrize Apr 17, 2021 5 - Production/Stable N/A :pypi:`pytest-nlcov` Pytest plugin to get the coverage of the new lines (based on git diff) only Jul 07, 2021 N/A N/A :pypi:`pytest-nocustom` Run all tests without custom markers Jul 07, 2021 5 - Production/Stable N/A :pypi:`pytest-nodev` Test-driven source code search for Python. Jul 21, 2016 4 - Beta pytest (>=2.8.1) :pypi:`pytest-nogarbage` Ensure a test produces no garbage Aug 29, 2021 5 - Production/Stable pytest (>=4.6.0) + :pypi:`pytest-nose-attrib` pytest plugin to use nose @attrib marks decorators and pick tests based on attributes and partially uses nose-attrib plugin approach Aug 13, 2023 N/A N/A :pypi:`pytest-notice` Send pytest execution result email Nov 05, 2020 N/A N/A :pypi:`pytest-notification` A pytest plugin for sending a desktop notification and playing a sound upon completion of tests Jun 19, 2020 N/A pytest (>=4) :pypi:`pytest-notifier` A pytest plugin to notify test result Jun 12, 2020 3 - Alpha pytest @@ -770,7 +787,7 @@ This list contains 1289 plugins. :pypi:`pytest-oar` PyTest plugin for the OAR testing framework May 02, 2023 N/A pytest>=6.0.1 :pypi:`pytest-object-getter` Import any object from a 3rd party module while mocking its namespace on demand. Jul 31, 2022 5 - Production/Stable pytest :pypi:`pytest-ochrus` pytest results data-base and HTML reporter Feb 21, 2018 4 - Beta N/A - :pypi:`pytest-odc` A pytest plugin for simplifying ODC database tests Jul 18, 2023 4 - Beta pytest (>=3.5.0) + :pypi:`pytest-odc` A pytest plugin for simplifying ODC database tests Aug 04, 2023 4 - Beta pytest (>=3.5.0) :pypi:`pytest-odoo` py.test plugin to run Odoo tests Jul 06, 2023 4 - Beta pytest (>=7.2.0) :pypi:`pytest-odoo-fixtures` Project description Jun 25, 2019 N/A N/A :pypi:`pytest-oerp` pytest plugin to test OpenERP modules Feb 28, 2012 3 - Alpha N/A @@ -821,7 +838,7 @@ This list contains 1289 plugins. :pypi:`pytest-pg` A tiny plugin for pytest which runs PostgreSQL in Docker May 04, 2023 5 - Production/Stable pytest (>=6.0.0) :pypi:`pytest-pgsql` Pytest plugins and helpers for tests using a Postgres database. May 13, 2020 5 - Production/Stable pytest (>=3.0.0) :pypi:`pytest-phmdoctest` pytest plugin to test Python examples in Markdown using phmdoctest. Apr 15, 2022 4 - Beta pytest (>=5.4.3) - :pypi:`pytest-picked` Run the tests related to the changed files Dec 23, 2020 N/A pytest (>=3.5.0) + :pypi:`pytest-picked` Run the tests related to the changed files Jul 27, 2023 N/A pytest (>=3.7.0) :pypi:`pytest-pigeonhole` Jun 25, 2018 5 - Production/Stable pytest (>=3.4) :pypi:`pytest-pikachu` Show surprise when tests are passing Aug 05, 2021 5 - Production/Stable pytest :pypi:`pytest-pilot` Slice in your test base thanks to powerful markers. Oct 09, 2020 5 - Production/Stable N/A @@ -833,7 +850,7 @@ This list contains 1289 plugins. :pypi:`pytest-platform-markers` Markers for pytest to skip tests on specific platforms Sep 09, 2019 4 - Beta pytest (>=3.6.0) :pypi:`pytest-play` pytest plugin that let you automate actions and assertions with test metrics reporting executing plain YAML files Jun 12, 2019 5 - Production/Stable N/A :pypi:`pytest-playbook` Pytest plugin for reading playbooks. Jan 21, 2021 3 - Alpha pytest (>=6.1.2,<7.0.0) - :pypi:`pytest-playwright` A pytest wrapper with fixtures for Playwright to automate web browsers Apr 24, 2023 N/A pytest (<8.0.0,>=6.2.4) + :pypi:`pytest-playwright` A pytest wrapper with fixtures for Playwright to automate web browsers Aug 07, 2023 N/A pytest (<8.0.0,>=6.2.4) :pypi:`pytest-playwright-async` ASYNC Pytest plugin for Playwright Jul 03, 2023 N/A N/A :pypi:`pytest-playwrights` A pytest wrapper with fixtures for Playwright to automate web browsers Dec 02, 2021 N/A N/A :pypi:`pytest-playwright-snapshot` A pytest wrapper for snapshot testing with playwright Aug 19, 2021 N/A N/A @@ -852,17 +869,17 @@ This list contains 1289 plugins. :pypi:`pytest-poo` Visualize your crappy tests Mar 25, 2021 5 - Production/Stable pytest (>=2.3.4) :pypi:`pytest-poo-fail` Visualize your failed tests with poo Feb 12, 2015 5 - Production/Stable N/A :pypi:`pytest-pop` A pytest plugin to help with testing pop projects May 09, 2023 5 - Production/Stable pytest - :pypi:`pytest-porringer` Jun 24, 2023 N/A pytest>=7.1.2 + :pypi:`pytest-porringer` Aug 19, 2023 N/A pytest>=7.4.0 :pypi:`pytest-portion` Select a portion of the collected tests Jan 28, 2021 4 - Beta pytest (>=3.5.0) :pypi:`pytest-postgres` Run PostgreSQL in Docker container in Pytest. Mar 22, 2020 N/A pytest :pypi:`pytest-postgresql` Postgresql fixtures and fixture factories for Pytest. May 20, 2023 5 - Production/Stable pytest (>=6.2) - :pypi:`pytest-pot` A package for enhancing pytest Nov 20, 2022 N/A N/A :pypi:`pytest-power` pytest plugin with powerful fixtures Dec 31, 2020 N/A pytest (>=5.4) :pypi:`pytest-prefer-nested-dup-tests` A Pytest plugin to drop duplicated tests during collection, but will prefer keeping nested packages. Apr 27, 2022 4 - Beta pytest (>=7.1.1,<8.0.0) :pypi:`pytest-pretty` pytest plugin for printing summary data as I want it Apr 05, 2023 5 - Production/Stable pytest>=7 :pypi:`pytest-pretty-terminal` pytest plugin for generating prettier terminal output Jan 31, 2022 N/A pytest (>=3.4.1) :pypi:`pytest-pride` Minitest-style test colors Apr 02, 2016 3 - Alpha N/A :pypi:`pytest-print` pytest-print adds the printer fixture you can use to print messages to the user (directly to the pytest runner, not stdout) Jun 28, 2023 5 - Production/Stable pytest>=7.3.2 + :pypi:`pytest-priority` pytest plugin for add priority for tests Jul 23, 2023 N/A N/A :pypi:`pytest-profiles` pytest plugin for configuration profiles Dec 09, 2021 4 - Beta pytest (>=3.7.0) :pypi:`pytest-profiling` Profiling plugin for py.test May 28, 2019 5 - Production/Stable pytest :pypi:`pytest-progress` pytest plugin for instant test progress status Jan 31, 2022 5 - Production/Stable N/A @@ -892,7 +909,7 @@ This list contains 1289 plugins. :pypi:`pytest-pyramid` pytest_pyramid - provides fixtures for testing pyramid applications with pytest test suite Dec 13, 2022 5 - Production/Stable pytest :pypi:`pytest-pyramid-server` Pyramid server fixture for py.test May 28, 2019 5 - Production/Stable pytest :pypi:`pytest-pyreport` PyReport is a lightweight reporting plugin for Pytest that provides concise HTML report Jul 02, 2023 N/A pytest (>=7.3.1) - :pypi:`pytest-pyright` Pytest plugin for type checking code with Pyright Nov 20, 2022 4 - Beta pytest (>=7.0.0) + :pypi:`pytest-pyright` Pytest plugin for type checking code with Pyright Aug 20, 2023 4 - Beta pytest >=7.0.0 :pypi:`pytest-pyspec` A plugin that transforms the pytest output into a result similar to the RSpec. It enables the use of docstrings to display results and also enables the use of the prefixes "describe", "with" and "it". Mar 12, 2023 5 - Production/Stable pytest (>=7.2.1,<8.0.0) :pypi:`pytest-pystack` Plugin to run pystack after a timeout for a test suite. May 07, 2023 N/A pytest (>=3.5.0) :pypi:`pytest-pytestrail` Pytest plugin for interaction with TestRail Aug 27, 2020 4 - Beta pytest (>=3.8.0) @@ -918,14 +935,14 @@ This list contains 1289 plugins. :pypi:`pytest-raisesregexp` Simple pytest plugin to look for regex in Exceptions Dec 18, 2015 N/A N/A :pypi:`pytest-raisin` Plugin enabling the use of exception instances with pytest.raises Feb 06, 2022 N/A pytest :pypi:`pytest-random` py.test plugin to randomize tests Apr 28, 2013 3 - Alpha N/A - :pypi:`pytest-randomly` Pytest plugin to randomly order tests and control random.seed. Jul 10, 2023 5 - Production/Stable pytest + :pypi:`pytest-randomly` Pytest plugin to randomly order tests and control random.seed. Aug 15, 2023 5 - Production/Stable pytest :pypi:`pytest-randomness` Pytest plugin about random seed management May 30, 2019 3 - Alpha N/A :pypi:`pytest-random-num` Randomise the order in which pytest tests are run with some control over the randomness Oct 19, 2020 5 - Production/Stable N/A :pypi:`pytest-random-order` Randomise the order in which pytest tests are run with some control over the randomness Dec 03, 2022 5 - Production/Stable pytest (>=3.0.0) :pypi:`pytest-readme` Test your README.md file Sep 02, 2022 5 - Production/Stable N/A - :pypi:`pytest-reana` Pytest fixtures for REANA. Dec 13, 2022 3 - Alpha N/A + :pypi:`pytest-reana` Pytest fixtures for REANA. Aug 04, 2023 3 - Alpha N/A :pypi:`pytest-recorder` Pytest plugin, meant to facilitate unit tests writing for tools consumming Web APIs. Mar 30, 2023 N/A N/A - :pypi:`pytest-recording` A pytest plugin that allows you recording of network interactions via VCR.py Feb 16, 2023 4 - Beta pytest (>=3.5.0) + :pypi:`pytest-recording` A pytest plugin that allows you recording of network interactions via VCR.py Jul 31, 2023 4 - Beta pytest>=3.5.0 :pypi:`pytest-recordings` Provides pytest plugins for reporting request/response traffic, screenshots, and more to ReportPortal Aug 13, 2020 N/A N/A :pypi:`pytest-redis` Redis fixtures and fixture factories for Pytest. Apr 19, 2023 5 - Production/Stable pytest (>=6.2) :pypi:`pytest-redislite` Pytest plugin for testing code using Redis Apr 05, 2022 4 - Beta pytest @@ -935,7 +952,7 @@ This list contains 1289 plugins. :pypi:`pytest-regex` Select pytest tests with regular expressions May 29, 2023 4 - Beta pytest (>=3.5.0) :pypi:`pytest-regex-dependency` Management of Pytest dependencies via regex patterns Jun 12, 2022 N/A pytest :pypi:`pytest-regressions` Easy to use fixtures to write regression tests. Jan 13, 2023 5 - Production/Stable pytest (>=6.2.0) - :pypi:`pytest-regtest` pytest plugin for regression tests Jul 08, 2022 N/A N/A + :pypi:`pytest-regtest` pytest plugin for regression tests Aug 17, 2023 N/A N/A :pypi:`pytest-relative-order` a pytest plugin that sorts tests using "before" and "after" markers May 17, 2021 4 - Beta N/A :pypi:`pytest-relaxed` Relaxed test discovery/organization for pytest May 23, 2023 5 - Production/Stable pytest (>=7) :pypi:`pytest-remfiles` Pytest plugin to create a temporary directory with remote files Jul 01, 2019 5 - Production/Stable N/A @@ -979,7 +996,7 @@ This list contains 1289 plugins. :pypi:`pytest-result-sender` Apr 20, 2023 N/A pytest>=7.3.1 :pypi:`pytest-resume` A Pytest plugin to resuming from the last run test Apr 22, 2023 4 - Beta pytest (>=7.0) :pypi:`pytest-rethinkdb` A RethinkDB plugin for pytest. Jul 24, 2016 4 - Beta N/A - :pypi:`pytest-retry` Adds the ability to retry flaky tests in CI environments Aug 16, 2022 N/A pytest (>=7.0.0) + :pypi:`pytest-retry` Adds the ability to retry flaky tests in CI environments Aug 02, 2023 N/A pytest (>=7.0.0) :pypi:`pytest-retry-class` A pytest plugin to rerun entire class on failure Mar 25, 2023 N/A pytest (>=5.3) :pypi:`pytest-reusable-testcases` Apr 28, 2023 N/A N/A :pypi:`pytest-reverse` Pytest plugin to reverse test order. Jul 10, 2023 5 - Production/Stable pytest @@ -990,13 +1007,14 @@ This list contains 1289 plugins. :pypi:`pytest-rmsis` Sycronise pytest results to Jira RMsis Aug 10, 2022 N/A pytest (>=5.3.5) :pypi:`pytest-rng` Fixtures for seeding tests and making randomness reproducible Aug 08, 2019 5 - Production/Stable pytest :pypi:`pytest-roast` pytest plugin for ROAST configuration override and fixtures Nov 09, 2022 5 - Production/Stable pytest + :pypi:`pytest-robotframework` a pytest plugin that can run both python and robotframework tests while generating robot reports for them Aug 19, 2023 N/A N/A :pypi:`pytest-rocketchat` Pytest to Rocket.Chat reporting plugin Apr 18, 2021 5 - Production/Stable N/A :pypi:`pytest-rotest` Pytest integration with rotest Sep 08, 2019 N/A pytest (>=3.5.0) :pypi:`pytest-rpc` Extend py.test for RPC OpenStack testing. Feb 22, 2019 4 - Beta pytest (~=3.6) :pypi:`pytest-rst` Test code from RST documents with pytest Jan 26, 2023 N/A N/A :pypi:`pytest-rt` pytest data collector plugin for Testgr May 05, 2022 N/A N/A :pypi:`pytest-rts` Coverage-based regression test selection (RTS) plugin for pytest May 17, 2021 N/A pytest - :pypi:`pytest-ruff` pytest plugin to check ruff requirements. Jun 08, 2023 4 - Beta N/A + :pypi:`pytest-ruff` pytest plugin to check ruff requirements. Jul 31, 2023 4 - Beta N/A :pypi:`pytest-run-changed` Pytest plugin that runs changed tests only Apr 02, 2021 3 - Alpha pytest :pypi:`pytest-runfailed` implement a --failed option for pytest Mar 24, 2016 N/A N/A :pypi:`pytest-runner` Invoke py.test as distutils command with dependency resolution Feb 25, 2022 5 - Production/Stable pytest (>=6) ; extra == 'testing' @@ -1008,29 +1026,30 @@ This list contains 1289 plugins. :pypi:`pytest-saccharin` pytest-saccharin is a updated fork of pytest-sugar, a plugin for pytest that changes the default look and feel of pytest (e.g. progressbar, show tests that fail instantly). Oct 31, 2022 3 - Alpha N/A :pypi:`pytest-salt` Pytest Salt Plugin Jan 27, 2020 4 - Beta N/A :pypi:`pytest-salt-containers` A Pytest plugin that builds and creates docker containers Nov 09, 2016 4 - Beta N/A - :pypi:`pytest-salt-factories` Pytest Salt Plugin Dec 15, 2022 4 - Beta pytest (>=6.0.0) + :pypi:`pytest-salt-factories` Pytest Salt Plugin Jul 31, 2023 4 - Beta pytest (>=6.0.0) :pypi:`pytest-salt-from-filenames` Simple PyTest Plugin For Salt's Test Suite Specifically Jan 29, 2019 4 - Beta pytest (>=4.1) :pypi:`pytest-salt-runtests-bridge` Simple PyTest Plugin For Salt's Test Suite Specifically Dec 05, 2019 4 - Beta pytest (>=4.1) :pypi:`pytest-sanic` a pytest plugin for Sanic Oct 25, 2021 N/A pytest (>=5.2) :pypi:`pytest-sanity` Dec 07, 2020 N/A N/A :pypi:`pytest-sa-pg` May 14, 2019 N/A N/A - :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Jul 20, 2023 5 - Production/Stable N/A + :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Aug 18, 2023 5 - Production/Stable N/A :pypi:`pytest-scenario` pytest plugin for test scenarios Feb 06, 2017 3 - Alpha N/A :pypi:`pytest-schedule` The job of test scheduling for humans. Jan 07, 2023 5 - Production/Stable N/A :pypi:`pytest-schema` 👍 Validate return values against a schema-like object in testing Mar 14, 2022 5 - Production/Stable pytest (>=3.5.0) - :pypi:`pytest-screenshot-on-failure` Saves a screenshot when a test case from a pytest execution fails Jul 18, 2023 4 - Beta N/A + :pypi:`pytest-screenshot-on-failure` Saves a screenshot when a test case from a pytest execution fails Jul 21, 2023 4 - Beta N/A :pypi:`pytest-securestore` An encrypted password store for use within pytest cases Nov 08, 2021 4 - Beta N/A :pypi:`pytest-select` A pytest plugin which allows to (de-)select tests from a file. Jan 18, 2019 3 - Alpha pytest (>=3.0) :pypi:`pytest-selenium` pytest plugin for Selenium May 28, 2023 5 - Production/Stable pytest>=6.0.0 - :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Jul 20, 2023 5 - Production/Stable N/A + :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Aug 18, 2023 5 - Production/Stable N/A :pypi:`pytest-selenium-enhancer` pytest plugin for Selenium Apr 29, 2022 5 - Production/Stable N/A :pypi:`pytest-selenium-pdiff` A pytest package implementing perceptualdiff for Selenium tests. Apr 06, 2017 2 - Pre-Alpha N/A + :pypi:`pytest-selenium-screenshot` pytest plugin to automatically capture screenshots upon selenium webdriver events Aug 20, 2023 N/A pytest >= 7.0.0 :pypi:`pytest-send-email` Send pytest execution result email Dec 04, 2019 N/A N/A :pypi:`pytest-sentry` A pytest plugin to send testrun information to Sentry.io Jan 05, 2023 N/A N/A :pypi:`pytest-sequence-markers` Pytest plugin for sequencing markers for execution of tests May 23, 2023 5 - Production/Stable N/A :pypi:`pytest-server-fixtures` Extensible server fixures for py.test May 28, 2019 5 - Production/Stable pytest :pypi:`pytest-serverless` Automatically mocks resources from serverless.yml in pytest using moto. May 09, 2022 4 - Beta N/A - :pypi:`pytest-servers` pytest servers Jul 13, 2023 3 - Alpha pytest (>=6.2) + :pypi:`pytest-servers` pytest servers Jul 26, 2023 3 - Alpha pytest (>=6.2) :pypi:`pytest-services` Services plugin for pytest testing framework Oct 30, 2020 6 - Mature N/A :pypi:`pytest-session2file` pytest-session2file (aka: pytest-session_to_file for v0.1.0 - v0.1.2) is a py.test plugin for capturing and saving to file the stdout of py.test. Jan 26, 2021 3 - Alpha pytest :pypi:`pytest-session-fixture-globalize` py.test plugin to make session fixtures behave as if written in conftest, even if it is written in some modules May 15, 2018 4 - Beta N/A @@ -1043,14 +1062,14 @@ This list contains 1289 plugins. :pypi:`pytest-shell` A pytest plugin to help with testing shell scripts / black box commands Mar 27, 2022 N/A N/A :pypi:`pytest-shell-utilities` Pytest plugin to simplify running shell commands against the system Jul 02, 2023 5 - Production/Stable pytest (>=7.1.0) :pypi:`pytest-sheraf` Versatile ZODB abstraction layer - pytest fixtures Feb 11, 2020 N/A pytest - :pypi:`pytest-sherlock` pytest plugin help to find coupled tests Jan 16, 2023 5 - Production/Stable pytest (>=3.5.1) + :pypi:`pytest-sherlock` pytest plugin help to find coupled tests Aug 14, 2023 5 - Production/Stable pytest >=3.5.1 :pypi:`pytest-shortcuts` Expand command-line shortcuts listed in pytest configuration Oct 29, 2020 4 - Beta pytest (>=3.5.0) :pypi:`pytest-shutil` A goodie-bag of unix shell and environment tools for py.test May 28, 2019 5 - Production/Stable pytest :pypi:`pytest-simplehttpserver` Simple pytest fixture to spin up an HTTP server Jun 24, 2021 4 - Beta N/A :pypi:`pytest-simple-plugin` Simple pytest plugin Nov 27, 2019 N/A N/A :pypi:`pytest-simple-settings` simple-settings plugin for pytest Nov 17, 2020 4 - Beta pytest :pypi:`pytest-single-file-logging` Allow for multiple processes to log to a single file May 05, 2016 4 - Beta pytest (>=2.8.1) - :pypi:`pytest-skip-markers` Pytest Salt Plugin Dec 20, 2022 5 - Production/Stable pytest (>=7.1.0) + :pypi:`pytest-skip-markers` Pytest Salt Plugin Jul 31, 2023 5 - Production/Stable pytest (>=7.1.0) :pypi:`pytest-skipper` A plugin that selects only tests with changes in execution path Mar 26, 2017 3 - Alpha pytest (>=3.0.6) :pypi:`pytest-skippy` Automatically skip tests that don't need to run! Jan 27, 2018 3 - Alpha pytest (>=2.3.4) :pypi:`pytest-skip-slow` A pytest plugin to skip \`@pytest.mark.slow\` tests by default. Feb 09, 2023 N/A pytest>=6.2.0 @@ -1067,6 +1086,7 @@ This list contains 1289 plugins. :pypi:`pytest-snail` Plugin for adding a marker to slow running tests. 🐌 Nov 04, 2019 3 - Alpha pytest (>=5.0.1) :pypi:`pytest-snapci` py.test plugin for Snap-CI Nov 12, 2015 N/A N/A :pypi:`pytest-snapshot` A plugin for snapshot testing with pytest. Apr 23, 2022 4 - Beta pytest (>=3.0.0) + :pypi:`pytest-snapshot-with-message-generator` A plugin for snapshot testing with pytest. Jul 25, 2023 4 - Beta pytest (>=3.0.0) :pypi:`pytest-snmpserver` May 12, 2021 N/A N/A :pypi:`pytest-snowflake-bdd` Setup test data and run tests on snowflake in BDD style! Jan 05, 2022 4 - Beta pytest (>=6.2.0) :pypi:`pytest-socket` Pytest Plugin to disable socket calls during tests Feb 03, 2023 4 - Beta pytest (>=3.6.3) @@ -1074,9 +1094,9 @@ This list contains 1289 plugins. :pypi:`pytest-soft-assertions` May 05, 2020 3 - Alpha pytest :pypi:`pytest-solidity` A PyTest library plugin for Solidity language. Jan 15, 2022 1 - Planning pytest (<7,>=6.0.1) ; extra == 'tests' :pypi:`pytest-solr` Solr process and client fixtures for py.test. May 11, 2020 3 - Alpha pytest (>=3.0.0) - :pypi:`pytest-sort` Tools for sorting test cases Jul 17, 2023 N/A pytest (>=7.0.0) + :pypi:`pytest-sort` Tools for sorting test cases Aug 12, 2023 N/A pytest >=7.0.0 :pypi:`pytest-sorter` A simple plugin to first execute tests that historically failed more Apr 20, 2021 4 - Beta pytest (>=3.1.1) - :pypi:`pytest-sosu` Unofficial PyTest plugin for Sauce Labs Feb 14, 2023 2 - Pre-Alpha pytest + :pypi:`pytest-sosu` Unofficial PyTest plugin for Sauce Labs Aug 04, 2023 2 - Pre-Alpha pytest :pypi:`pytest-sourceorder` Test-ordering plugin for pytest Sep 01, 2021 4 - Beta pytest :pypi:`pytest-spark` pytest plugin to run the tests with support of pyspark. Feb 23, 2020 4 - Beta pytest :pypi:`pytest-spawner` py.test plugin to spawn process and communicate with them. Jul 31, 2015 4 - Beta N/A @@ -1091,7 +1111,7 @@ This list contains 1289 plugins. :pypi:`pytest-splitio` Split.io SDK integration for e2e tests Sep 22, 2020 N/A pytest (<7,>=5.0) :pypi:`pytest-split-tests` A Pytest plugin for running a subset of your tests by splitting them in to equally sized groups. Forked from Mark Adams' original project pytest-test-groups. Jul 30, 2021 5 - Production/Stable pytest (>=2.5) :pypi:`pytest-split-tests-tresorit` Feb 22, 2021 1 - Planning N/A - :pypi:`pytest-splunk-addon` A Dynamic test tool for Splunk Apps and Add-ons Jun 30, 2023 N/A pytest (>5.4.0,<8) + :pypi:`pytest-splunk-addon` A Dynamic test tool for Splunk Apps and Add-ons Jul 25, 2023 N/A pytest (>5.4.0,<8) :pypi:`pytest-splunk-addon-ui-smartx` Library to support testing Splunk Add-on UX Mar 07, 2023 N/A N/A :pypi:`pytest-splunk-env` pytest fixtures for interaction with Splunk Enterprise and Splunk Cloud Oct 22, 2020 N/A pytest (>=6.1.1,<7.0.0) :pypi:`pytest-sqitch` sqitch for pytest Apr 06, 2020 4 - Beta N/A @@ -1110,7 +1130,7 @@ This list contains 1289 plugins. :pypi:`pytest-stepfunctions` A small description May 08, 2021 4 - Beta pytest :pypi:`pytest-steps` Create step-wise / incremental tests in pytest. Sep 23, 2021 5 - Production/Stable N/A :pypi:`pytest-stepwise` Run a test suite one failing test at a time. Dec 01, 2015 4 - Beta N/A - :pypi:`pytest-stf` pytest plugin for openSTF Dec 04, 2022 N/A pytest (>=5.0) + :pypi:`pytest-stf` pytest plugin for openSTF Aug 16, 2023 N/A pytest >=5.0 :pypi:`pytest-stoq` A plugin to pytest stoq Feb 09, 2021 4 - Beta N/A :pypi:`pytest-stress` A Pytest plugin that allows you to loop tests for a user defined amount of time. Dec 07, 2019 4 - Beta pytest (>=3.6.0) :pypi:`pytest-structlog` Structured logging assertions Dec 18, 2022 N/A pytest @@ -1138,6 +1158,7 @@ This list contains 1289 plugins. :pypi:`pytest-target` Pytest plugin for remote target orchestration. Jan 21, 2021 3 - Alpha pytest (>=6.1.2,<7.0.0) :pypi:`pytest-tblineinfo` tblineinfo is a py.test plugin that insert the node id in the final py.test report when --tb=line option is used Dec 01, 2015 3 - Alpha pytest (>=2.0) :pypi:`pytest-tcpclient` A pytest plugin for testing TCP clients Nov 16, 2022 N/A pytest (<8,>=7.1.3) + :pypi:`pytest-tdd` run pytest on a python module Aug 18, 2023 4 - Beta N/A :pypi:`pytest-teamcity-logblock` py.test plugin to introduce block structure in teamcity build log, if output is not captured May 15, 2018 4 - Beta N/A :pypi:`pytest-telegram` Pytest to Telegram reporting plugin Dec 10, 2020 5 - Production/Stable N/A :pypi:`pytest-telegram-notifier` Telegram notification plugin for Pytest Jun 27, 2023 5 - Production/Stable N/A @@ -1148,7 +1169,7 @@ This list contains 1289 plugins. :pypi:`pytest-testbook` A plugin to run tests written in Jupyter notebook Dec 11, 2016 3 - Alpha N/A :pypi:`pytest-testconfig` Test configuration plugin for pytest. Jan 11, 2020 4 - Beta pytest (>=3.5.0) :pypi:`pytest-testdirectory` A py.test plugin providing temporary directories in unit tests. May 02, 2023 5 - Production/Stable pytest - :pypi:`pytest-testdox` A testdox format reporter for pytest Apr 19, 2022 5 - Production/Stable pytest (>=4.6.0) + :pypi:`pytest-testdox` A testdox format reporter for pytest Jul 22, 2023 5 - Production/Stable pytest (>=4.6.0) :pypi:`pytest-test-grouping` A Pytest plugin for running a subset of your tests by splitting them in to equally sized groups. Feb 01, 2023 5 - Production/Stable pytest (>=2.5) :pypi:`pytest-test-groups` A Pytest plugin for running a subset of your tests by splitting them in to equally sized groups. Oct 25, 2016 5 - Production/Stable N/A :pypi:`pytest-testinfra` Test infrastructures May 21, 2023 5 - Production/Stable pytest (!=3.0.2) @@ -1174,7 +1195,7 @@ This list contains 1289 plugins. :pypi:`pytest-testslide` TestSlide fixture for pytest Jan 07, 2021 5 - Production/Stable pytest (~=6.2) :pypi:`pytest-test-this` Plugin for py.test to run relevant tests, based on naively checking if a test contains a reference to the symbol you supply Sep 15, 2019 2 - Pre-Alpha pytest (>=2.3) :pypi:`pytest-test-utils` Jul 14, 2022 N/A pytest (>=5) - :pypi:`pytest-tesults` Tesults plugin for pytest Dec 23, 2022 5 - Production/Stable pytest (>=3.5.0) + :pypi:`pytest-tesults` Tesults plugin for pytest Jul 21, 2023 5 - Production/Stable pytest (>=3.5.0) :pypi:`pytest-textual-snapshot` Snapshot testing for Textual apps Jul 18, 2023 4 - Beta pytest (>=7.0.0) :pypi:`pytest-tezos` pytest-ligo Jan 16, 2020 4 - Beta N/A :pypi:`pytest-th2-bdd` pytest_th2_bdd May 13, 2022 N/A N/A @@ -1226,7 +1247,7 @@ This list contains 1289 plugins. :pypi:`pytest-twisted` A twisted plugin for pytest. Oct 16, 2022 5 - Production/Stable pytest (>=2.3) :pypi:`pytest-typechecker` Run type checkers on specified test files Feb 04, 2022 N/A pytest (>=6.2.5,<7.0.0) :pypi:`pytest-typhoon-config` A Typhoon HIL plugin that facilitates test parameter configuration at runtime Apr 07, 2022 5 - Production/Stable N/A - :pypi:`pytest-typhoon-xray` Typhoon HIL plugin for pytest Jun 10, 2023 4 - Beta N/A + :pypi:`pytest-typhoon-xray` Typhoon HIL plugin for pytest Aug 15, 2023 4 - Beta N/A :pypi:`pytest-tytest` Typhoon HIL plugin for pytest May 25, 2020 4 - Beta pytest (>=5.4.2) :pypi:`pytest-ubersmith` Easily mock calls to ubersmith at the \`requests\` level. Apr 13, 2015 N/A N/A :pypi:`pytest-ui` Text User Interface for running python tests Jul 05, 2021 4 - Beta pytest @@ -1238,7 +1259,7 @@ This list contains 1289 plugins. :pypi:`pytest-unmarked` Run only unmarked tests Aug 27, 2019 5 - Production/Stable N/A :pypi:`pytest-unordered` Test equality of unordered collections in pytest Nov 28, 2022 4 - Beta pytest (>=6.0.0) :pypi:`pytest-unstable` Set a test as unstable to return 0 even if it failed Sep 27, 2022 4 - Beta N/A - :pypi:`pytest-unused-fixtures` A pytest plugin to list unused fixtures after a test run. Jun 30, 2023 4 - Beta pytest (>=7.3.2,<8.0.0) + :pypi:`pytest-unused-fixtures` A pytest plugin to list unused fixtures after a test run. Aug 08, 2023 4 - Beta pytest (>=7.3.2,<8.0.0) :pypi:`pytest-upload-report` pytest-upload-report is a plugin for pytest that upload your test report for test results. Jun 18, 2021 5 - Production/Stable N/A :pypi:`pytest-utils` Some helpers for pytest. Feb 02, 2023 4 - Beta pytest (>=7.0.0,<8.0.0) :pypi:`pytest-vagrant` A py.test plugin providing access to vagrant. Sep 07, 2021 5 - Production/Stable pytest @@ -1282,9 +1303,10 @@ This list contains 1289 plugins. :pypi:`pytest-xdist-debug-for-graingert` pytest xdist plugin for distributed testing and loop-on-failing modes Jul 24, 2019 5 - Production/Stable pytest (>=4.4.0) :pypi:`pytest-xdist-forked` forked from pytest-xdist Feb 10, 2020 5 - Production/Stable pytest (>=4.4.0) :pypi:`pytest-xdist-tracker` pytest plugin helps to reproduce failures for particular xdist node Nov 18, 2021 3 - Alpha pytest (>=3.5.1) - :pypi:`pytest-xdist-worker-stats` A pytest plugin to list worker statistics after a xdist run. Jun 19, 2023 4 - Beta pytest (>=7.3.2,<8.0.0) + :pypi:`pytest-xdist-worker-stats` A pytest plugin to list worker statistics after a xdist run. Aug 08, 2023 4 - Beta pytest (>=7.3.2,<8.0.0) :pypi:`pytest-xfaillist` Maintain a xfaillist in an additional file to avoid merge-conflicts. Sep 17, 2021 N/A pytest (>=6.2.2,<7.0.0) :pypi:`pytest-xfiles` Pytest fixtures providing data read from function, module or package related (x)files. Feb 27, 2018 N/A N/A + :pypi:`pytest-xiuyu` This is a pytest plugin Jul 25, 2023 5 - Production/Stable N/A :pypi:`pytest-xlog` Extended logging for test and decorators May 31, 2020 4 - Beta N/A :pypi:`pytest-xlsx` pytest plugin for generating test cases by xlsx(excel) Jul 03, 2023 N/A pytest<8,>=7.4.0 :pypi:`pytest-xpara` An extended parametrizing plugin of pytest. Oct 30, 2017 3 - Alpha pytest @@ -1294,7 +1316,7 @@ This list contains 1289 plugins. :pypi:`pytest-xray-server` May 03, 2022 3 - Alpha pytest (>=5.3.1) :pypi:`pytest-xskynet` A package to prevent Dependency Confusion attacks against Yandex. Feb 10, 2023 N/A N/A :pypi:`pytest-xvfb` A pytest plugin to run Xvfb (or Xephyr/Xvnc) for tests. May 29, 2023 4 - Beta pytest (>=2.8.1) - :pypi:`pytest-xvirt` A pytest plugin to virtualize test. For example to transparently running them on a remote box. Jun 18, 2023 4 - Beta pytest (>=7.1.0) + :pypi:`pytest-xvirt` A pytest plugin to virtualize test. For example to transparently running them on a remote box. Jul 30, 2023 4 - Beta pytest (>=7.1.0) :pypi:`pytest-yaml` This plugin is used to load yaml output to your test using pytest framework. Oct 05, 2018 N/A pytest :pypi:`pytest-yaml-sanmu` pytest plugin for generating test cases by yaml Jul 03, 2023 N/A pytest>=7.4.0 :pypi:`pytest-yamltree` Create or check file/directory trees described by YAML Mar 02, 2020 4 - Beta pytest (>=3.1.1) @@ -1323,6 +1345,13 @@ This list contains 1289 plugins. Simple but powerful assertion and verification of logged lines. + :pypi:`nuts` + *last release*: Aug 11, 2023, + *status*: N/A, + *requires*: pytest (>=7.3.0,<8.0.0) + + Network Unit Testing System + :pypi:`pytest-abq` *last release*: Apr 07, 2023, *status*: N/A, @@ -1351,6 +1380,13 @@ This list contains 1289 plugins. pytest plugin for generating test execution results within Jira Test Management (tm4j) + :pypi:`pytest-adaptavist-fixed` + *last release*: Aug 15, 2023, + *status*: N/A, + *requires*: N/A + + pytest plugin for generating test execution results within Jira Test Management (tm4j) + :pypi:`pytest-addons-test` *last release*: Aug 02, 2021, *status*: N/A, @@ -1526,6 +1562,13 @@ This list contains 1289 plugins. Static code checks used at Alphamoon + :pypi:`pytest-analyzer` + *last release*: Aug 21, 2023, + *status*: N/A, + *requires*: pytest >=7.3.1 + + this plugin allows to analyze tests in pytest project, collect test metadata and sync it with testomat.io TCM system + :pypi:`pytest-android` *last release*: Feb 21, 2019, *status*: 3 - Alpha, @@ -1548,9 +1591,9 @@ This list contains 1289 plugins. pytest-annotate: Generate PyAnnotate annotations from your pytest tests. :pypi:`pytest-ansible` - *last release*: May 15, 2023, + *last release*: Aug 09, 2023, *status*: 5 - Production/Stable, - *requires*: pytest (<8.0.0,>=6) + *requires*: pytest <8.0.0,>=6 Plugin for pytest to simplify calling ansible modules from tests or fixtures @@ -1786,7 +1829,7 @@ This list contains 1289 plugins. Pytest support for asyncio :pypi:`pytest-asyncio-cooperative` - *last release*: May 31, 2023, + *last release*: Aug 06, 2023, *status*: N/A, *requires*: N/A @@ -1911,6 +1954,13 @@ This list contains 1289 plugins. pytest plugin for axe-selenium-python + :pypi:`pytest-axe-playwright-snapshot` + *last release*: Jul 25, 2023, + *status*: N/A, + *requires*: pytest + + A pytest plugin that runs Axe-core on Playwright pages and takes snapshots of the results. + :pypi:`pytest-azure` *last release*: Jan 18, 2023, *status*: 3 - Alpha, @@ -1974,6 +2024,13 @@ This list contains 1289 plugins. BDD for pytest + :pypi:`pytest-bdd-report` + *last release*: Aug 20, 2023, + *status*: N/A, + *requires*: N/A + + A pytest-bdd plugin for generating useful and informative BDD test reports + :pypi:`pytest-bdd-splinter` *last release*: Aug 12, 2019, *status*: 5 - Production/Stable, @@ -2087,7 +2144,7 @@ This list contains 1289 plugins. A pytest plugin helps developers to debug by providing useful commits history. :pypi:`pytest-blender` - *last release*: Jan 04, 2023, + *last release*: Aug 10, 2023, *status*: N/A, *requires*: pytest ; extra == 'dev' @@ -2262,9 +2319,9 @@ This list contains 1289 plugins. pytest plugin with mechanisms for caching across test runs :pypi:`pytest-cache-assert` - *last release*: Feb 26, 2023, + *last release*: Aug 14, 2023, *status*: 5 - Production/Stable, - *requires*: pytest (>=5.0.0) + *requires*: pytest (>=6.0.0) Cache assertion data to simplify regression testing of complex serializable data @@ -2409,14 +2466,14 @@ This list contains 1289 plugins. A pytest fixture for changing current working directory :pypi:`pytest-check` - *last release*: Jul 14, 2023, + *last release*: Aug 11, 2023, *status*: N/A, *requires*: pytest A pytest plugin that allows multiple failures per test. :pypi:`pytest-checkdocs` - *last release*: Jul 09, 2023, + *last release*: Jul 30, 2023, *status*: 5 - Production/Stable, *requires*: pytest (>=6) ; extra == 'testing' @@ -2626,12 +2683,19 @@ This list contains 1289 plugins. pytest plugin to run pycodestyle :pypi:`pytest-codspeed` - *last release*: Jul 04, 2023, + *last release*: Jul 27, 2023, *status*: 5 - Production/Stable, *requires*: pytest>=3.8 Pytest plugin to create CodSpeed benchmarks + :pypi:`pytest-collect-appoint-info` + *last release*: Aug 03, 2023, + *status*: N/A, + *requires*: pytest + + set your encoding + :pypi:`pytest-collect-formatter` *last release*: Mar 29, 2021, *status*: 5 - Production/Stable, @@ -3116,9 +3180,9 @@ This list contains 1289 plugins. A pytest plugin for linting a dbt project's conventions :pypi:`pytest-dbt-core` - *last release*: May 03, 2023, + *last release*: Aug 09, 2023, *status*: N/A, - *requires*: pytest (>=6.2.5) ; extra == 'test' + *requires*: pytest >=6.2.5 ; extra == 'test' Pytest extension for dbt. @@ -3136,6 +3200,13 @@ This list contains 1289 plugins. Pytest plugin to run unit tests for dbx (Databricks CLI extensions) related code + :pypi:`pytest-dc` + *last release*: Aug 16, 2023, + *status*: 5 - Production/Stable, + *requires*: pytest >=3.3 + + Manages Docker containers during your integration tests + :pypi:`pytest-deadfixtures` *last release*: Jul 23, 2020, *status*: 5 - Production/Stable, @@ -3143,6 +3214,13 @@ This list contains 1289 plugins. A simple plugin to list unused fixtures in pytest + :pypi:`pytest-deduplicate` + *last release*: Aug 12, 2023, + *status*: 4 - Beta, + *requires*: pytest + + Identifies duplicate unit tests + :pypi:`pytest-deepcov` *last release*: Mar 30, 2021, *status*: N/A, @@ -3325,6 +3403,13 @@ This list contains 1289 plugins. Integrate CasperJS with your django tests as a pytest fixture. + :pypi:`pytest-django-class` + *last release*: Aug 08, 2023, + *status*: 4 - Beta, + *requires*: N/A + + A pytest plugin for running django in class-scoped fixtures + :pypi:`pytest-django-dotenv` *last release*: Nov 26, 2019, *status*: 4 - Beta, @@ -3599,9 +3684,9 @@ This list contains 1289 plugins. A simple pytest plugin to import names and add them to the doctest namespace. :pypi:`pytest-doctestplus` - *last release*: Jun 08, 2023, + *last release*: Aug 11, 2023, *status*: 3 - Alpha, - *requires*: pytest (>=4.6) + *requires*: pytest >=4.6 Pytest plugin with advanced doctest features. @@ -3612,6 +3697,13 @@ This list contains 1289 plugins. pytest plugin for dogu report + :pypi:`pytest-dogu-sdk` + *last release*: Aug 04, 2023, + *status*: N/A, + *requires*: N/A + + pytest plugin for the Dogu + :pypi:`pytest-dolphin` *last release*: Nov 30, 2016, *status*: 4 - Beta, @@ -3774,9 +3866,9 @@ This list contains 1289 plugins. Pytest plugin to select test using Ekstazi algorithm :pypi:`pytest-elasticsearch` - *last release*: Mar 01, 2022, + *last release*: Aug 03, 2023, *status*: 5 - Production/Stable, - *requires*: pytest (>=6.2.0) + *requires*: pytest (>=6.2) Elasticsearch fixtures and fixture factories for Pytest. @@ -3899,6 +3991,13 @@ This list contains 1289 plugins. set your encoding and logger + :pypi:`pytest-encoding` + *last release*: Aug 11, 2023, + *status*: N/A, + *requires*: pytest + + set your encoding and logger + :pypi:`pytest-enhanced-reports` *last release*: Dec 15, 2022, *status*: N/A, @@ -4005,7 +4104,7 @@ This list contains 1289 plugins. Pytest plugin for testing examples in docstrings and markdown files. :pypi:`pytest-excel` - *last release*: Jan 31, 2022, + *last release*: Jul 20, 2023, *status*: 5 - Production/Stable, *requires*: N/A @@ -4089,12 +4188,19 @@ This list contains 1289 plugins. A Pytest plugin to ignore certain marked tests by default :pypi:`pytest-exploratory` - *last release*: Feb 21, 2022, + *last release*: Aug 18, 2023, *status*: N/A, *requires*: pytest (>=6.2) Interactive console for pytest. + :pypi:`pytest-explorer` + *last release*: Aug 01, 2023, + *status*: N/A, + *requires*: N/A + + terminal ui for exploring and running tests + :pypi:`pytest-extensions` *last release*: Aug 17, 2022, *status*: 4 - Beta, @@ -4537,7 +4643,7 @@ This list contains 1289 plugins. A pytest plugin to shim pytest commandline options for fowards compatibility :pypi:`pytest-frappe` - *last release*: May 03, 2023, + *last release*: Aug 07, 2023, *status*: 4 - Beta, *requires*: pytest>=7.0.0 @@ -4656,7 +4762,7 @@ This list contains 1289 plugins. For finding/executing Ghost Inspector tests :pypi:`pytest-girder` - *last release*: Jun 28, 2023, + *last release*: Jul 24, 2023, *status*: N/A, *requires*: N/A @@ -4894,9 +5000,9 @@ This list contains 1289 plugins. A pytest plugin for use with homeassistant custom components. :pypi:`pytest-homeassistant-custom-component` - *last release*: Jul 14, 2023, + *last release*: Aug 19, 2023, *status*: 3 - Alpha, - *requires*: pytest (==7.3.1) + *requires*: pytest ==7.3.1 Experimental package to automatically extract test plugins for Home Assistant custom components @@ -4950,12 +5056,19 @@ This list contains 1289 plugins. Helpers for testing hpfeeds in your python project :pypi:`pytest-html` - *last release*: Apr 08, 2023, + *last release*: Aug 13, 2023, *status*: 5 - Production/Stable, *requires*: pytest (!=6.0.0,>=5.0) pytest plugin for generating HTML reports + :pypi:`pytest-html-cn` + *last release*: Aug 01, 2023, + *status*: 5 - Production/Stable, + *requires*: N/A + + pytest plugin for generating HTML reports + :pypi:`pytest-html-lee` *last release*: Jun 30, 2020, *status*: 5 - Production/Stable, @@ -5048,14 +5161,14 @@ This list contains 1289 plugins. pytest-httpserver is a httpserver for pytest :pypi:`pytest-httptesting` - *last release*: Jul 09, 2023, + *last release*: Jul 24, 2023, *status*: N/A, *requires*: pytest (>=7.2.0,<8.0.0) http_testing framework on top of pytest :pypi:`pytest-httpx` - *last release*: Apr 12, 2023, + *last release*: Aug 02, 2023, *status*: 5 - Production/Stable, *requires*: pytest (<8.0,>=6.0) @@ -5089,6 +5202,13 @@ This list contains 1289 plugins. help hypo module for pytest + :pypi:`pytest-iam` + *last release*: Aug 21, 2023, + *status*: 3 - Alpha, + *requires*: pytest (>=7.0.0,<8.0.0) + + A fully functional OAUTH2 / OpenID Connect (OIDC) server to be used in your testsuite + :pypi:`pytest-ibutsu` *last release*: Aug 05, 2022, *status*: 4 - Beta, @@ -5131,6 +5251,13 @@ This list contains 1289 plugins. ignore failures from flaky tests (pytest plugin) + :pypi:`pytest-ignore-test-results` + *last release*: Aug 17, 2023, + *status*: 2 - Pre-Alpha, + *requires*: pytest>=7.0 + + A pytest plugin to ignore test results. + :pypi:`pytest-image-diff` *last release*: Mar 09, 2023, *status*: 3 - Alpha, @@ -5188,7 +5315,7 @@ This list contains 1289 plugins. A pytest plugin for writing inline tests. :pypi:`pytest-inmanta` - *last release*: Feb 23, 2023, + *last release*: Aug 03, 2023, *status*: 5 - Production/Stable, *requires*: N/A @@ -5678,9 +5805,9 @@ This list contains 1289 plugins. A pytest plugin to show the line numbers of test functions :pypi:`pytest-line-profiler` - *last release*: May 03, 2021, + *last release*: Aug 10, 2023, *status*: 4 - Beta, - *requires*: pytest (>=3.5.0) + *requires*: pytest >=3.5.0 Profile code executed by pytest @@ -5712,6 +5839,13 @@ This list contains 1289 plugins. A pytest plugin that stream output in LITF format + :pypi:`pytest-litter` + *last release*: Aug 08, 2023, + *status*: 4 - Beta, + *requires*: pytest >=6.1 + + Pytest plugin which verifies that tests do not modify file trees. + :pypi:`pytest-live` *last release*: Mar 08, 2020, *status*: N/A, @@ -5748,7 +5882,7 @@ This list contains 1289 plugins. Pytest plugin for AWS integration tests :pypi:`pytest-lockable` - *last release*: Jul 20, 2022, + *last release*: Aug 09, 2023, *status*: 5 - Production/Stable, *requires*: pytest @@ -6133,7 +6267,7 @@ This list contains 1289 plugins. An in-memory mock of a Redis server that runs in a separate thread. This is to be used for unit-tests that require a Redis database. :pypi:`pytest-mock-resources` - *last release*: Jul 12, 2023, + *last release*: Jul 24, 2023, *status*: N/A, *requires*: pytest (>=1.0) @@ -6196,9 +6330,9 @@ This list contains 1289 plugins. PyTest Molecule Plugin :: discover and run molecule tests :pypi:`pytest-mongo` - *last release*: Jun 07, 2021, + *last release*: Jul 20, 2023, *status*: 5 - Production/Stable, - *requires*: pytest + *requires*: pytest (>=6.2) MongoDB process and client fixtures plugin for Pytest. @@ -6280,7 +6414,7 @@ This list contains 1289 plugins. low-startup-overhead, scalable, distributed-testing pytest plugin :pypi:`pytest-mqtt` - *last release*: Mar 15, 2023, + *last release*: Aug 03, 2023, *status*: 4 - Beta, *requires*: pytest (<8) ; extra == 'test' @@ -6336,7 +6470,7 @@ This list contains 1289 plugins. Mypy static type checker plugin for Pytest :pypi:`pytest-mypy-plugins` - *last release*: Jun 29, 2023, + *last release*: Jul 25, 2023, *status*: 4 - Beta, *requires*: pytest (>=7.0.0) @@ -6441,7 +6575,7 @@ This list contains 1289 plugins. pytest ngs fixtures :pypi:`pytest-nhsd-apim` - *last release*: Jul 11, 2023, + *last release*: Aug 02, 2023, *status*: N/A, *requires*: pytest (==6.2.5) @@ -6489,6 +6623,13 @@ This list contains 1289 plugins. Ensure a test produces no garbage + :pypi:`pytest-nose-attrib` + *last release*: Aug 13, 2023, + *status*: N/A, + *requires*: N/A + + pytest plugin to use nose @attrib marks decorators and pick tests based on attributes and partially uses nose-attrib plugin approach + :pypi:`pytest-notice` *last release*: Nov 05, 2020, *status*: N/A, @@ -6553,7 +6694,7 @@ This list contains 1289 plugins. pytest results data-base and HTML reporter :pypi:`pytest-odc` - *last release*: Jul 18, 2023, + *last release*: Aug 04, 2023, *status*: 4 - Beta, *requires*: pytest (>=3.5.0) @@ -6910,9 +7051,9 @@ This list contains 1289 plugins. pytest plugin to test Python examples in Markdown using phmdoctest. :pypi:`pytest-picked` - *last release*: Dec 23, 2020, + *last release*: Jul 27, 2023, *status*: N/A, - *requires*: pytest (>=3.5.0) + *requires*: pytest (>=3.7.0) Run the tests related to the changed files @@ -6994,7 +7135,7 @@ This list contains 1289 plugins. Pytest plugin for reading playbooks. :pypi:`pytest-playwright` - *last release*: Apr 24, 2023, + *last release*: Aug 07, 2023, *status*: N/A, *requires*: pytest (<8.0.0,>=6.2.4) @@ -7127,9 +7268,9 @@ This list contains 1289 plugins. A pytest plugin to help with testing pop projects :pypi:`pytest-porringer` - *last release*: Jun 24, 2023, + *last release*: Aug 19, 2023, *status*: N/A, - *requires*: pytest>=7.1.2 + *requires*: pytest>=7.4.0 @@ -7154,13 +7295,6 @@ This list contains 1289 plugins. Postgresql fixtures and fixture factories for Pytest. - :pypi:`pytest-pot` - *last release*: Nov 20, 2022, - *status*: N/A, - *requires*: N/A - - A package for enhancing pytest - :pypi:`pytest-power` *last release*: Dec 31, 2020, *status*: N/A, @@ -7203,6 +7337,13 @@ This list contains 1289 plugins. pytest-print adds the printer fixture you can use to print messages to the user (directly to the pytest runner, not stdout) + :pypi:`pytest-priority` + *last release*: Jul 23, 2023, + *status*: N/A, + *requires*: N/A + + pytest plugin for add priority for tests + :pypi:`pytest-profiles` *last release*: Dec 09, 2021, *status*: 4 - Beta, @@ -7407,9 +7548,9 @@ This list contains 1289 plugins. PyReport is a lightweight reporting plugin for Pytest that provides concise HTML report :pypi:`pytest-pyright` - *last release*: Nov 20, 2022, + *last release*: Aug 20, 2023, *status*: 4 - Beta, - *requires*: pytest (>=7.0.0) + *requires*: pytest >=7.0.0 Pytest plugin for type checking code with Pyright @@ -7589,7 +7730,7 @@ This list contains 1289 plugins. py.test plugin to randomize tests :pypi:`pytest-randomly` - *last release*: Jul 10, 2023, + *last release*: Aug 15, 2023, *status*: 5 - Production/Stable, *requires*: pytest @@ -7624,7 +7765,7 @@ This list contains 1289 plugins. Test your README.md file :pypi:`pytest-reana` - *last release*: Dec 13, 2022, + *last release*: Aug 04, 2023, *status*: 3 - Alpha, *requires*: N/A @@ -7638,9 +7779,9 @@ This list contains 1289 plugins. Pytest plugin, meant to facilitate unit tests writing for tools consumming Web APIs. :pypi:`pytest-recording` - *last release*: Feb 16, 2023, + *last release*: Jul 31, 2023, *status*: 4 - Beta, - *requires*: pytest (>=3.5.0) + *requires*: pytest>=3.5.0 A pytest plugin that allows you recording of network interactions via VCR.py @@ -7708,7 +7849,7 @@ This list contains 1289 plugins. Easy to use fixtures to write regression tests. :pypi:`pytest-regtest` - *last release*: Jul 08, 2022, + *last release*: Aug 17, 2023, *status*: N/A, *requires*: N/A @@ -8016,7 +8157,7 @@ This list contains 1289 plugins. A RethinkDB plugin for pytest. :pypi:`pytest-retry` - *last release*: Aug 16, 2022, + *last release*: Aug 02, 2023, *status*: N/A, *requires*: pytest (>=7.0.0) @@ -8092,6 +8233,13 @@ This list contains 1289 plugins. pytest plugin for ROAST configuration override and fixtures + :pypi:`pytest-robotframework` + *last release*: Aug 19, 2023, + *status*: N/A, + *requires*: N/A + + a pytest plugin that can run both python and robotframework tests while generating robot reports for them + :pypi:`pytest-rocketchat` *last release*: Apr 18, 2021, *status*: 5 - Production/Stable, @@ -8135,7 +8283,7 @@ This list contains 1289 plugins. Coverage-based regression test selection (RTS) plugin for pytest :pypi:`pytest-ruff` - *last release*: Jun 08, 2023, + *last release*: Jul 31, 2023, *status*: 4 - Beta, *requires*: N/A @@ -8219,7 +8367,7 @@ This list contains 1289 plugins. A Pytest plugin that builds and creates docker containers :pypi:`pytest-salt-factories` - *last release*: Dec 15, 2022, + *last release*: Jul 31, 2023, *status*: 4 - Beta, *requires*: pytest (>=6.0.0) @@ -8261,7 +8409,7 @@ This list contains 1289 plugins. :pypi:`pytest-sbase` - *last release*: Jul 20, 2023, + *last release*: Aug 18, 2023, *status*: 5 - Production/Stable, *requires*: N/A @@ -8289,7 +8437,7 @@ This list contains 1289 plugins. 👍 Validate return values against a schema-like object in testing :pypi:`pytest-screenshot-on-failure` - *last release*: Jul 18, 2023, + *last release*: Jul 21, 2023, *status*: 4 - Beta, *requires*: N/A @@ -8317,7 +8465,7 @@ This list contains 1289 plugins. pytest plugin for Selenium :pypi:`pytest-seleniumbase` - *last release*: Jul 20, 2023, + *last release*: Aug 18, 2023, *status*: 5 - Production/Stable, *requires*: N/A @@ -8337,6 +8485,13 @@ This list contains 1289 plugins. A pytest package implementing perceptualdiff for Selenium tests. + :pypi:`pytest-selenium-screenshot` + *last release*: Aug 20, 2023, + *status*: N/A, + *requires*: pytest >= 7.0.0 + + pytest plugin to automatically capture screenshots upon selenium webdriver events + :pypi:`pytest-send-email` *last release*: Dec 04, 2019, *status*: N/A, @@ -8373,7 +8528,7 @@ This list contains 1289 plugins. Automatically mocks resources from serverless.yml in pytest using moto. :pypi:`pytest-servers` - *last release*: Jul 13, 2023, + *last release*: Jul 26, 2023, *status*: 3 - Alpha, *requires*: pytest (>=6.2) @@ -8464,9 +8619,9 @@ This list contains 1289 plugins. Versatile ZODB abstraction layer - pytest fixtures :pypi:`pytest-sherlock` - *last release*: Jan 16, 2023, + *last release*: Aug 14, 2023, *status*: 5 - Production/Stable, - *requires*: pytest (>=3.5.1) + *requires*: pytest >=3.5.1 pytest plugin help to find coupled tests @@ -8513,7 +8668,7 @@ This list contains 1289 plugins. Allow for multiple processes to log to a single file :pypi:`pytest-skip-markers` - *last release*: Dec 20, 2022, + *last release*: Jul 31, 2023, *status*: 5 - Production/Stable, *requires*: pytest (>=7.1.0) @@ -8631,6 +8786,13 @@ This list contains 1289 plugins. A plugin for snapshot testing with pytest. + :pypi:`pytest-snapshot-with-message-generator` + *last release*: Jul 25, 2023, + *status*: 4 - Beta, + *requires*: pytest (>=3.0.0) + + A plugin for snapshot testing with pytest. + :pypi:`pytest-snmpserver` *last release*: May 12, 2021, *status*: N/A, @@ -8681,9 +8843,9 @@ This list contains 1289 plugins. Solr process and client fixtures for py.test. :pypi:`pytest-sort` - *last release*: Jul 17, 2023, + *last release*: Aug 12, 2023, *status*: N/A, - *requires*: pytest (>=7.0.0) + *requires*: pytest >=7.0.0 Tools for sorting test cases @@ -8695,7 +8857,7 @@ This list contains 1289 plugins. A simple plugin to first execute tests that historically failed more :pypi:`pytest-sosu` - *last release*: Feb 14, 2023, + *last release*: Aug 04, 2023, *status*: 2 - Pre-Alpha, *requires*: pytest @@ -8800,7 +8962,7 @@ This list contains 1289 plugins. :pypi:`pytest-splunk-addon` - *last release*: Jun 30, 2023, + *last release*: Jul 25, 2023, *status*: N/A, *requires*: pytest (>5.4.0,<8) @@ -8933,9 +9095,9 @@ This list contains 1289 plugins. Run a test suite one failing test at a time. :pypi:`pytest-stf` - *last release*: Dec 04, 2022, + *last release*: Aug 16, 2023, *status*: N/A, - *requires*: pytest (>=5.0) + *requires*: pytest >=5.0 pytest plugin for openSTF @@ -9128,6 +9290,13 @@ This list contains 1289 plugins. A pytest plugin for testing TCP clients + :pypi:`pytest-tdd` + *last release*: Aug 18, 2023, + *status*: 4 - Beta, + *requires*: N/A + + run pytest on a python module + :pypi:`pytest-teamcity-logblock` *last release*: May 15, 2018, *status*: 4 - Beta, @@ -9199,7 +9368,7 @@ This list contains 1289 plugins. A py.test plugin providing temporary directories in unit tests. :pypi:`pytest-testdox` - *last release*: Apr 19, 2022, + *last release*: Jul 22, 2023, *status*: 5 - Production/Stable, *requires*: pytest (>=4.6.0) @@ -9381,7 +9550,7 @@ This list contains 1289 plugins. :pypi:`pytest-tesults` - *last release*: Dec 23, 2022, + *last release*: Jul 21, 2023, *status*: 5 - Production/Stable, *requires*: pytest (>=3.5.0) @@ -9745,7 +9914,7 @@ This list contains 1289 plugins. A Typhoon HIL plugin that facilitates test parameter configuration at runtime :pypi:`pytest-typhoon-xray` - *last release*: Jun 10, 2023, + *last release*: Aug 15, 2023, *status*: 4 - Beta, *requires*: N/A @@ -9829,7 +9998,7 @@ This list contains 1289 plugins. Set a test as unstable to return 0 even if it failed :pypi:`pytest-unused-fixtures` - *last release*: Jun 30, 2023, + *last release*: Aug 08, 2023, *status*: 4 - Beta, *requires*: pytest (>=7.3.2,<8.0.0) @@ -10137,7 +10306,7 @@ This list contains 1289 plugins. pytest plugin helps to reproduce failures for particular xdist node :pypi:`pytest-xdist-worker-stats` - *last release*: Jun 19, 2023, + *last release*: Aug 08, 2023, *status*: 4 - Beta, *requires*: pytest (>=7.3.2,<8.0.0) @@ -10157,6 +10326,13 @@ This list contains 1289 plugins. Pytest fixtures providing data read from function, module or package related (x)files. + :pypi:`pytest-xiuyu` + *last release*: Jul 25, 2023, + *status*: 5 - Production/Stable, + *requires*: N/A + + This is a pytest plugin + :pypi:`pytest-xlog` *last release*: May 31, 2020, *status*: 4 - Beta, @@ -10221,7 +10397,7 @@ This list contains 1289 plugins. A pytest plugin to run Xvfb (or Xephyr/Xvnc) for tests. :pypi:`pytest-xvirt` - *last release*: Jun 18, 2023, + *last release*: Jul 30, 2023, *status*: 4 - Beta, *requires*: pytest (>=7.1.0) From d1722d5c189ff7a1baccadfb514d05402104ccee Mon Sep 17 00:00:00 2001 From: Reagan Lee <96998476+reaganjlee@users.noreply.github.com> Date: Mon, 21 Aug 2023 15:49:39 -0700 Subject: [PATCH 29/34] fix test for codecov --- testing/test_assertrewrite.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/testing/test_assertrewrite.py b/testing/test_assertrewrite.py index 2c908133d..08813c4dc 100644 --- a/testing/test_assertrewrite.py +++ b/testing/test_assertrewrite.py @@ -685,8 +685,9 @@ class TestAssertionRewrite: assert msg is not None assert " < 0" in msg - def test_assert_handling_raise_in__iter__(self) -> None: - def f() -> None: + def test_assert_handling_raise_in__iter__(self, pytester: Pytester) -> None: + pytester.makepyfile( + """\ class A: def __iter__(self): raise ValueError() @@ -698,10 +699,10 @@ class TestAssertionRewrite: return "" assert A() == A() - - msg = getmsg(f) - assert msg is not None - assert " == " in msg + """ + ) + result = pytester.runpytest() + result.stdout.fnmatch_lines(["*E*assert == "]) def test_formatchar(self) -> None: def f() -> None: From 3f446b68fdbd8f1e0e0d9af3960e1da90f58f1b3 Mon Sep 17 00:00:00 2001 From: WarrenTheRabbit <37808734+WarrenTheRabbit@users.noreply.github.com> Date: Tue, 22 Aug 2023 14:36:39 +1000 Subject: [PATCH 30/34] doc: fix docstring spelling in pytester --- src/_pytest/pytester.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/_pytest/pytester.py b/src/_pytest/pytester.py index b112e6e70..649338599 100644 --- a/src/_pytest/pytester.py +++ b/src/_pytest/pytester.py @@ -829,7 +829,7 @@ class Pytester: return self._makefile(ext, args, kwargs) def makeconftest(self, source: str) -> Path: - """Write a contest.py file. + """Write a conftest.py file. :param source: The contents. :returns: The conftest.py file. From cada6c105a7f9e22d5519c0e9355cc44df2a58b8 Mon Sep 17 00:00:00 2001 From: DetachHead <57028336+DetachHead@users.noreply.github.com> Date: Tue, 22 Aug 2023 17:57:59 +1000 Subject: [PATCH 31/34] ignore mypy error on deprecated `Instance` usage --- testing/deprecated_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/deprecated_test.py b/testing/deprecated_test.py index f4197a1f6..08e193b5c 100644 --- a/testing/deprecated_test.py +++ b/testing/deprecated_test.py @@ -272,7 +272,7 @@ def test_importing_instance_is_deprecated(pytester: Pytester) -> None: pytest.PytestDeprecationWarning, match=re.escape("The pytest.Instance collector type is deprecated"), ): - pytest.Instance + pytest.Instance # type:ignore[attr-defined] with pytest.warns( pytest.PytestDeprecationWarning, From 8f36fd5454f6d3c9fa33ecb7403641bfa713ab87 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 22 Aug 2023 08:10:48 +0000 Subject: [PATCH 32/34] [pre-commit.ci] pre-commit autoupdate (#11335) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/asottile/blacken-docs: 1.15.0 → 1.16.0](https://github.com/asottile/blacken-docs/compare/1.15.0...1.16.0) - [github.com/pre-commit/mirrors-mypy: v1.5.0 → v1.5.1](https://github.com/pre-commit/mirrors-mypy/compare/v1.5.0...v1.5.1) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index d9d488dd1..82dc5dae7 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -5,7 +5,7 @@ repos: - id: black args: [--safe, --quiet] - repo: https://github.com/asottile/blacken-docs - rev: 1.15.0 + rev: 1.16.0 hooks: - id: blacken-docs additional_dependencies: [black==23.7.0] @@ -56,7 +56,7 @@ repos: hooks: - id: python-use-type-annotations - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.5.0 + rev: v1.5.1 hooks: - id: mypy files: ^(src/|testing/) From 23b899f31f91a05a75d06bcc5e8c99891b210541 Mon Sep 17 00:00:00 2001 From: Ha Pam Date: Wed, 23 Aug 2023 15:17:09 +0700 Subject: [PATCH 33/34] Fix a typo in anatomy.rst (#11341) --- doc/en/explanation/anatomy.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/en/explanation/anatomy.rst b/doc/en/explanation/anatomy.rst index e86dd7425..93d3400da 100644 --- a/doc/en/explanation/anatomy.rst +++ b/doc/en/explanation/anatomy.rst @@ -34,7 +34,7 @@ a function/method call. **Assert** is where we look at that resulting state and check if it looks how we'd expect after the dust has settled. It's where we gather evidence to say the -behavior does or does not aligns with what we expect. The ``assert`` in our test +behavior does or does not align with what we expect. The ``assert`` in our test is where we take that measurement/observation and apply our judgement to it. If something should be green, we'd say ``assert thing == "green"``. From 7500fe44b2aed9fec71251b7826f726d9b403428 Mon Sep 17 00:00:00 2001 From: Jon Parise Date: Wed, 23 Aug 2023 02:21:17 -0700 Subject: [PATCH 34/34] Correct the spelling of ArgSource.INVOCATION_DIR (#11333) Config.ArgsSource.INCOVATION_DIR remains as a backwards compatibility alias. --- changelog/11333.trivial.rst | 2 ++ src/_pytest/config/__init__.py | 5 +++-- testing/test_config.py | 18 ++++++++++++++++++ 3 files changed, 23 insertions(+), 2 deletions(-) create mode 100644 changelog/11333.trivial.rst diff --git a/changelog/11333.trivial.rst b/changelog/11333.trivial.rst new file mode 100644 index 000000000..846f79e34 --- /dev/null +++ b/changelog/11333.trivial.rst @@ -0,0 +1,2 @@ +Corrected the spelling of ``Config.ArgsSource.INVOCATION_DIR``. +The previous spelling ``INCOVATION_DIR`` remains as an alias. diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index 8dbaf7c70..1d9c49aa1 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -953,7 +953,8 @@ class Config: #: Command line arguments. ARGS = enum.auto() #: Invocation directory. - INCOVATION_DIR = enum.auto() + INVOCATION_DIR = enum.auto() + INCOVATION_DIR = INVOCATION_DIR # backwards compatibility alias #: 'testpaths' configuration value. TESTPATHS = enum.auto() @@ -1278,7 +1279,7 @@ class Config: else: result = [] if not result: - source = Config.ArgsSource.INCOVATION_DIR + source = Config.ArgsSource.INVOCATION_DIR result = [str(invocation_dir)] return result, source diff --git a/testing/test_config.py b/testing/test_config.py index 04161f238..ded307901 100644 --- a/testing/test_config.py +++ b/testing/test_config.py @@ -507,6 +507,24 @@ class TestParseIni: result = pytester.runpytest("--foo=1") result.stdout.fnmatch_lines("* no tests ran in *") + def test_args_source_args(self, pytester: Pytester): + config = pytester.parseconfig("--", "test_filename.py") + assert config.args_source == Config.ArgsSource.ARGS + + def test_args_source_invocation_dir(self, pytester: Pytester): + config = pytester.parseconfig() + assert config.args_source == Config.ArgsSource.INVOCATION_DIR + + def test_args_source_testpaths(self, pytester: Pytester): + pytester.makeini( + """ + [pytest] + testpaths=* + """ + ) + config = pytester.parseconfig() + assert config.args_source == Config.ArgsSource.TESTPATHS + class TestConfigCmdlineParsing: def test_parsing_again_fails(self, pytester: Pytester) -> None: