1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221
|
# mypy: allow-untyped-defs
from __future__ import annotations
from pathlib import Path
import re
import sys
from _pytest import deprecated
from _pytest.compat import legacy_path
from _pytest.pytester import Pytester
import pytest
from pytest import PytestDeprecationWarning
@pytest.mark.parametrize("plugin", sorted(deprecated.DEPRECATED_EXTERNAL_PLUGINS))
@pytest.mark.filterwarnings("default")
def test_external_plugins_integrated(pytester: Pytester, plugin) -> None:
pytester.syspathinsert()
pytester.makepyfile(**{plugin: ""})
with pytest.warns(pytest.PytestConfigWarning):
pytester.parseconfig("-p", plugin)
def test_hookspec_via_function_attributes_are_deprecated():
from _pytest.config import PytestPluginManager
pm = PytestPluginManager()
class DeprecatedHookMarkerSpec:
def pytest_bad_hook(self):
pass
pytest_bad_hook.historic = False # type: ignore[attr-defined]
with pytest.warns(
PytestDeprecationWarning,
match=r"Please use the pytest\.hookspec\(historic=False\) decorator",
) as recorder:
pm.add_hookspecs(DeprecatedHookMarkerSpec)
(record,) = recorder
assert (
record.lineno
== DeprecatedHookMarkerSpec.pytest_bad_hook.__code__.co_firstlineno
)
assert record.filename == __file__
def test_hookimpl_via_function_attributes_are_deprecated():
from _pytest.config import PytestPluginManager
pm = PytestPluginManager()
class DeprecatedMarkImplPlugin:
def pytest_runtest_call(self):
pass
pytest_runtest_call.tryfirst = True # type: ignore[attr-defined]
with pytest.warns(
PytestDeprecationWarning,
match=r"Please use the pytest.hookimpl\(tryfirst=True\)",
) as recorder:
pm.register(DeprecatedMarkImplPlugin())
(record,) = recorder
assert (
record.lineno
== DeprecatedMarkImplPlugin.pytest_runtest_call.__code__.co_firstlineno
)
assert record.filename == __file__
def test_yield_fixture_is_deprecated() -> None:
with pytest.warns(DeprecationWarning, match=r"yield_fixture is deprecated"):
@pytest.yield_fixture
def fix():
assert False
def test_private_is_deprecated() -> None:
class PrivateInit:
def __init__(self, foo: int, *, _ispytest: bool = False) -> None:
deprecated.check_ispytest(_ispytest)
with pytest.warns(
pytest.PytestDeprecationWarning, match="private pytest class or function"
):
PrivateInit(10)
# Doesn't warn.
PrivateInit(10, _ispytest=True)
@pytest.mark.parametrize("hooktype", ["hook", "ihook"])
def test_hookproxy_warnings_for_pathlib(tmp_path, hooktype, request):
path = legacy_path(tmp_path)
PATH_WARN_MATCH = r".*path: py\.path\.local\) argument is deprecated, please use \(collection_path: pathlib\.Path.*"
if hooktype == "ihook":
hooks = request.node.ihook
else:
hooks = request.config.hook
with pytest.warns(PytestDeprecationWarning, match=PATH_WARN_MATCH) as r:
l1 = sys._getframe().f_lineno
hooks.pytest_ignore_collect(
config=request.config, path=path, collection_path=tmp_path
)
l2 = sys._getframe().f_lineno
(record,) = r
assert record.filename == __file__
assert l1 < record.lineno < l2
hooks.pytest_ignore_collect(config=request.config, collection_path=tmp_path)
# Passing entirely *different* paths is an outright error.
with pytest.raises(ValueError, match=r"path.*fspath.*need to be equal"):
with pytest.warns(PytestDeprecationWarning, match=PATH_WARN_MATCH) as r:
hooks.pytest_ignore_collect(
config=request.config, path=path, collection_path=Path("/bla/bla")
)
def test_hookimpl_warnings_for_pathlib() -> None:
class Plugin:
def pytest_ignore_collect(self, path: object) -> None:
raise NotImplementedError()
def pytest_collect_file(self, path: object) -> None:
raise NotImplementedError()
def pytest_pycollect_makemodule(self, path: object) -> None:
raise NotImplementedError()
def pytest_report_header(self, startdir: object) -> str:
raise NotImplementedError()
def pytest_report_collectionfinish(self, startdir: object) -> str:
raise NotImplementedError()
pm = pytest.PytestPluginManager()
with pytest.warns(
pytest.PytestRemovedIn9Warning,
match=r"py\.path\.local.* argument is deprecated",
) as wc:
pm.register(Plugin())
assert len(wc.list) == 5
def test_node_ctor_fspath_argument_is_deprecated(pytester: Pytester) -> None:
mod = pytester.getmodulecol("")
class MyFile(pytest.File):
def collect(self):
raise NotImplementedError()
with pytest.warns(
pytest.PytestDeprecationWarning,
match=re.escape(
"The (fspath: py.path.local) argument to MyFile is deprecated."
),
):
MyFile.from_parent(
parent=mod.parent,
fspath=legacy_path("bla"),
)
def test_fixture_disallow_on_marked_functions():
"""Test that applying @pytest.fixture to a marked function warns (#3364)."""
with pytest.warns(
pytest.PytestRemovedIn9Warning,
match=r"Marks applied to fixtures have no effect",
) as record:
@pytest.fixture
@pytest.mark.parametrize("example", ["hello"])
@pytest.mark.usefixtures("tmp_path")
def foo():
raise NotImplementedError()
# it's only possible to get one warning here because you're already prevented
# from applying @fixture twice
# ValueError("fixture is being applied more than once to the same function")
assert len(record) == 1
def test_fixture_disallow_marks_on_fixtures():
"""Test that applying a mark to a fixture warns (#3364)."""
with pytest.warns(
pytest.PytestRemovedIn9Warning,
match=r"Marks applied to fixtures have no effect",
) as record:
@pytest.mark.parametrize("example", ["hello"])
@pytest.mark.usefixtures("tmp_path")
@pytest.fixture
def foo():
raise NotImplementedError()
assert len(record) == 2 # one for each mark decorator
# should point to this file
assert all(rec.filename == __file__ for rec in record)
def test_fixture_disallowed_between_marks():
"""Test that applying a mark to a fixture warns (#3364)."""
with pytest.warns(
pytest.PytestRemovedIn9Warning,
match=r"Marks applied to fixtures have no effect",
) as record:
@pytest.mark.parametrize("example", ["hello"])
@pytest.fixture
@pytest.mark.usefixtures("tmp_path")
def foo():
raise NotImplementedError()
assert len(record) == 2 # one for each mark decorator
|