2020-10-06 22:48:34 +08:00
|
|
|
import re
|
2021-04-03 20:51:36 +08:00
|
|
|
import sys
|
2020-08-15 16:35:54 +08:00
|
|
|
import warnings
|
2021-10-06 00:07:07 +08:00
|
|
|
from pathlib import Path
|
2019-10-17 03:52:04 +08:00
|
|
|
|
2016-07-23 22:56:04 +08:00
|
|
|
import pytest
|
2019-06-13 05:49:51 +08:00
|
|
|
from _pytest import deprecated
|
2021-03-21 06:39:38 +08:00
|
|
|
from _pytest.compat import legacy_path
|
2020-11-06 16:48:20 +08:00
|
|
|
from _pytest.pytester import Pytester
|
2021-03-21 06:39:38 +08:00
|
|
|
from pytest import PytestDeprecationWarning
|
2016-07-23 22:56:04 +08:00
|
|
|
|
|
|
|
|
2019-07-06 06:04:55 +08:00
|
|
|
@pytest.mark.parametrize("plugin", sorted(deprecated.DEPRECATED_EXTERNAL_PLUGINS))
|
2018-12-12 06:02:36 +08:00
|
|
|
@pytest.mark.filterwarnings("default")
|
2020-12-16 12:16:05 +08:00
|
|
|
def test_external_plugins_integrated(pytester: Pytester, plugin) -> None:
|
|
|
|
pytester.syspathinsert()
|
|
|
|
pytester.makepyfile(**{plugin: ""})
|
2019-06-13 05:49:51 +08:00
|
|
|
|
|
|
|
with pytest.warns(pytest.PytestConfigWarning):
|
2020-12-16 12:16:05 +08:00
|
|
|
pytester.parseconfig("-p", plugin)
|
2019-11-14 05:20:44 +08:00
|
|
|
|
|
|
|
|
2021-10-03 22:01:40 +08:00
|
|
|
def test_hookspec_via_function_attributes_are_deprecated():
|
|
|
|
from _pytest.config import PytestPluginManager
|
|
|
|
|
|
|
|
pm = PytestPluginManager()
|
|
|
|
|
|
|
|
class DeprecatedHookMarkerSpec:
|
|
|
|
def pytest_bad_hook(self):
|
|
|
|
pass
|
|
|
|
|
2022-07-31 23:11:34 +08:00
|
|
|
pytest_bad_hook.historic = False # type: ignore[attr-defined]
|
2021-10-03 22:01:40 +08:00
|
|
|
|
|
|
|
with pytest.warns(
|
|
|
|
PytestDeprecationWarning,
|
2022-07-31 23:11:34 +08:00
|
|
|
match=r"Please use the pytest\.hookspec\(historic=False\) decorator",
|
2021-10-03 22:01:40 +08:00
|
|
|
) 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__
|
|
|
|
|
|
|
|
|
2020-12-16 12:16:05 +08:00
|
|
|
def test_fscollector_gethookproxy_isinitpath(pytester: Pytester) -> None:
|
|
|
|
module = pytester.getmodulecol(
|
2020-08-15 16:35:54 +08:00
|
|
|
"""
|
|
|
|
def test_foo(): pass
|
|
|
|
""",
|
|
|
|
withinit=True,
|
|
|
|
)
|
|
|
|
assert isinstance(module, pytest.Module)
|
|
|
|
package = module.parent
|
|
|
|
assert isinstance(package, pytest.Package)
|
|
|
|
|
|
|
|
with pytest.warns(pytest.PytestDeprecationWarning, match="gethookproxy"):
|
2020-12-16 12:16:05 +08:00
|
|
|
package.gethookproxy(pytester.path)
|
2020-08-15 16:35:54 +08:00
|
|
|
|
|
|
|
with pytest.warns(pytest.PytestDeprecationWarning, match="isinitpath"):
|
2020-12-16 12:16:05 +08:00
|
|
|
package.isinitpath(pytester.path)
|
2020-08-15 16:35:54 +08:00
|
|
|
|
|
|
|
# The methods on Session are *not* deprecated.
|
|
|
|
session = module.session
|
|
|
|
with warnings.catch_warnings(record=True) as rec:
|
2020-12-16 12:16:05 +08:00
|
|
|
session.gethookproxy(pytester.path)
|
|
|
|
session.isinitpath(pytester.path)
|
2020-08-15 16:35:54 +08:00
|
|
|
assert len(rec) == 0
|
2020-11-06 16:48:20 +08:00
|
|
|
|
|
|
|
|
|
|
|
def test_strict_option_is_deprecated(pytester: Pytester) -> None:
|
|
|
|
"""--strict is a deprecated alias to --strict-markers (#7530)."""
|
|
|
|
pytester.makepyfile(
|
|
|
|
"""
|
|
|
|
import pytest
|
|
|
|
|
|
|
|
@pytest.mark.unknown
|
|
|
|
def test_foo(): pass
|
|
|
|
"""
|
|
|
|
)
|
2023-06-23 19:36:48 +08:00
|
|
|
result = pytester.runpytest("--strict", "-Wdefault::pytest.PytestRemovedIn8Warning")
|
2020-11-06 16:48:20 +08:00
|
|
|
result.stdout.fnmatch_lines(
|
|
|
|
[
|
|
|
|
"'unknown' not found in `markers` configuration option",
|
2021-11-15 05:11:22 +08:00
|
|
|
"*PytestRemovedIn8Warning: The --strict option is deprecated, use --strict-markers instead.",
|
2020-11-06 16:48:20 +08:00
|
|
|
]
|
|
|
|
)
|
2020-11-01 04:44:10 +08:00
|
|
|
|
|
|
|
|
|
|
|
def test_yield_fixture_is_deprecated() -> None:
|
|
|
|
with pytest.warns(DeprecationWarning, match=r"yield_fixture is deprecated"):
|
|
|
|
|
|
|
|
@pytest.yield_fixture
|
|
|
|
def fix():
|
|
|
|
assert False
|
2020-09-28 03:20:31 +08:00
|
|
|
|
|
|
|
|
|
|
|
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)
|
2021-01-15 00:14:39 +08:00
|
|
|
|
|
|
|
|
2021-04-03 20:51:36 +08:00
|
|
|
@pytest.mark.parametrize("hooktype", ["hook", "ihook"])
|
2021-12-03 20:14:09 +08:00
|
|
|
def test_hookproxy_warnings_for_pathlib(tmp_path, hooktype, request):
|
2021-03-21 06:39:38 +08:00
|
|
|
path = legacy_path(tmp_path)
|
|
|
|
|
2021-12-03 20:14:09 +08:00
|
|
|
PATH_WARN_MATCH = r".*path: py\.path\.local\) argument is deprecated, please use \(collection_path: pathlib\.Path.*"
|
2021-04-03 20:51:36 +08:00
|
|
|
if hooktype == "ihook":
|
|
|
|
hooks = request.node.ihook
|
|
|
|
else:
|
|
|
|
hooks = request.config.hook
|
2021-04-02 06:58:05 +08:00
|
|
|
|
|
|
|
with pytest.warns(PytestDeprecationWarning, match=PATH_WARN_MATCH) as r:
|
2021-04-03 20:51:36 +08:00
|
|
|
l1 = sys._getframe().f_lineno
|
2021-12-03 20:14:09 +08:00
|
|
|
hooks.pytest_ignore_collect(
|
|
|
|
config=request.config, path=path, collection_path=tmp_path
|
|
|
|
)
|
2021-04-03 20:51:36 +08:00
|
|
|
l2 = sys._getframe().f_lineno
|
2021-04-02 06:58:05 +08:00
|
|
|
|
|
|
|
(record,) = r
|
|
|
|
assert record.filename == __file__
|
2021-04-03 20:51:36 +08:00
|
|
|
assert l1 < record.lineno < l2
|
|
|
|
|
2021-12-03 20:14:09 +08:00
|
|
|
hooks.pytest_ignore_collect(config=request.config, collection_path=tmp_path)
|
2021-05-15 22:15:43 +08:00
|
|
|
|
2021-10-06 00:07:07 +08:00
|
|
|
# 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(
|
2021-12-03 20:14:09 +08:00
|
|
|
config=request.config, path=path, collection_path=Path("/bla/bla")
|
2021-10-06 00:07:07 +08:00
|
|
|
)
|
|
|
|
|
2021-05-15 22:15:43 +08:00
|
|
|
|
|
|
|
def test_warns_none_is_deprecated():
|
|
|
|
with pytest.warns(
|
|
|
|
PytestDeprecationWarning,
|
2021-05-17 16:23:08 +08:00
|
|
|
match=re.escape(
|
2022-01-14 02:32:22 +08:00
|
|
|
"Passing None has been deprecated.\n"
|
|
|
|
"See https://docs.pytest.org/en/latest/how-to/capture-warnings.html"
|
|
|
|
"#additional-use-cases-of-warnings-in-tests"
|
|
|
|
" for alternatives in common use cases."
|
2021-05-17 16:23:08 +08:00
|
|
|
),
|
2021-05-15 22:15:43 +08:00
|
|
|
):
|
2021-05-17 16:50:59 +08:00
|
|
|
with pytest.warns(None): # type: ignore[call-overload]
|
2021-05-16 19:07:39 +08:00
|
|
|
pass
|
2021-07-31 21:53:43 +08:00
|
|
|
|
|
|
|
|
2021-11-08 22:31:14 +08:00
|
|
|
class TestSkipMsgArgumentDeprecated:
|
|
|
|
def test_skip_with_msg_is_deprecated(self, pytester: Pytester) -> None:
|
|
|
|
p = pytester.makepyfile(
|
|
|
|
"""
|
|
|
|
import pytest
|
|
|
|
|
|
|
|
def test_skipping_msg():
|
|
|
|
pytest.skip(msg="skippedmsg")
|
|
|
|
"""
|
|
|
|
)
|
2023-06-23 19:36:48 +08:00
|
|
|
result = pytester.runpytest(p, "-Wdefault::pytest.PytestRemovedIn8Warning")
|
2021-11-08 22:31:14 +08:00
|
|
|
result.stdout.fnmatch_lines(
|
|
|
|
[
|
2021-11-15 05:11:22 +08:00
|
|
|
"*PytestRemovedIn8Warning: pytest.skip(msg=...) is now deprecated, "
|
2021-11-08 22:31:14 +08:00
|
|
|
"use pytest.skip(reason=...) instead",
|
|
|
|
'*pytest.skip(msg="skippedmsg")*',
|
|
|
|
]
|
|
|
|
)
|
|
|
|
result.assert_outcomes(skipped=1, warnings=1)
|
|
|
|
|
|
|
|
def test_fail_with_msg_is_deprecated(self, pytester: Pytester) -> None:
|
|
|
|
p = pytester.makepyfile(
|
|
|
|
"""
|
|
|
|
import pytest
|
|
|
|
|
|
|
|
def test_failing_msg():
|
|
|
|
pytest.fail(msg="failedmsg")
|
|
|
|
"""
|
|
|
|
)
|
2023-06-23 19:36:48 +08:00
|
|
|
result = pytester.runpytest(p, "-Wdefault::pytest.PytestRemovedIn8Warning")
|
2021-11-08 22:31:14 +08:00
|
|
|
result.stdout.fnmatch_lines(
|
|
|
|
[
|
2021-11-15 05:11:22 +08:00
|
|
|
"*PytestRemovedIn8Warning: pytest.fail(msg=...) is now deprecated, "
|
2021-11-08 22:31:14 +08:00
|
|
|
"use pytest.fail(reason=...) instead",
|
|
|
|
'*pytest.fail(msg="failedmsg")',
|
|
|
|
]
|
|
|
|
)
|
|
|
|
result.assert_outcomes(failed=1, warnings=1)
|
|
|
|
|
|
|
|
def test_exit_with_msg_is_deprecated(self, pytester: Pytester) -> None:
|
|
|
|
p = pytester.makepyfile(
|
|
|
|
"""
|
|
|
|
import pytest
|
|
|
|
|
|
|
|
def test_exit_msg():
|
|
|
|
pytest.exit(msg="exitmsg")
|
|
|
|
"""
|
|
|
|
)
|
2023-06-23 19:36:48 +08:00
|
|
|
result = pytester.runpytest(p, "-Wdefault::pytest.PytestRemovedIn8Warning")
|
2021-11-08 22:31:14 +08:00
|
|
|
result.stdout.fnmatch_lines(
|
|
|
|
[
|
2021-11-15 05:11:22 +08:00
|
|
|
"*PytestRemovedIn8Warning: pytest.exit(msg=...) is now deprecated, "
|
2021-11-08 22:31:14 +08:00
|
|
|
"use pytest.exit(reason=...) instead",
|
|
|
|
]
|
|
|
|
)
|
|
|
|
result.assert_outcomes(warnings=1)
|
|
|
|
|
|
|
|
|
2021-07-31 21:53:43 +08:00
|
|
|
def test_deprecation_of_cmdline_preparse(pytester: Pytester) -> None:
|
|
|
|
pytester.makeconftest(
|
|
|
|
"""
|
|
|
|
def pytest_cmdline_preparse(config, args):
|
|
|
|
...
|
|
|
|
|
|
|
|
"""
|
|
|
|
)
|
2023-06-23 19:36:48 +08:00
|
|
|
result = pytester.runpytest("-Wdefault::pytest.PytestRemovedIn8Warning")
|
2021-07-31 21:53:43 +08:00
|
|
|
result.stdout.fnmatch_lines(
|
|
|
|
[
|
2021-11-15 05:11:22 +08:00
|
|
|
"*PytestRemovedIn8Warning: The pytest_cmdline_preparse hook is deprecated*",
|
2021-07-31 21:53:43 +08:00
|
|
|
"*Please use pytest_load_initial_conftests hook instead.*",
|
|
|
|
]
|
|
|
|
)
|
2021-10-24 03:05:56 +08:00
|
|
|
|
|
|
|
|
|
|
|
def test_node_ctor_fspath_argument_is_deprecated(pytester: Pytester) -> None:
|
|
|
|
mod = pytester.getmodulecol("")
|
|
|
|
|
|
|
|
with pytest.warns(
|
|
|
|
pytest.PytestDeprecationWarning,
|
|
|
|
match=re.escape("The (fspath: py.path.local) argument to File is deprecated."),
|
|
|
|
):
|
|
|
|
pytest.File.from_parent(
|
|
|
|
parent=mod.parent,
|
|
|
|
fspath=legacy_path("bla"),
|
|
|
|
)
|
2021-11-13 20:03:44 +08:00
|
|
|
|
|
|
|
|
|
|
|
def test_importing_instance_is_deprecated(pytester: Pytester) -> None:
|
|
|
|
with pytest.warns(
|
|
|
|
pytest.PytestDeprecationWarning,
|
|
|
|
match=re.escape("The pytest.Instance collector type is deprecated"),
|
|
|
|
):
|
|
|
|
pytest.Instance
|
|
|
|
|
|
|
|
with pytest.warns(
|
|
|
|
pytest.PytestDeprecationWarning,
|
|
|
|
match=re.escape("The pytest.Instance collector type is deprecated"),
|
|
|
|
):
|
|
|
|
from _pytest.python import Instance # noqa: F401
|
2022-10-10 20:48:26 +08:00
|
|
|
|
|
|
|
|
|
|
|
def test_fixture_disallow_on_marked_functions():
|
|
|
|
"""Test that applying @pytest.fixture to a marked function warns (#3364)."""
|
|
|
|
with pytest.warns(
|
2023-06-25 23:08:53 +08:00
|
|
|
pytest.PytestRemovedIn8Warning,
|
2022-10-10 20:48:26 +08:00
|
|
|
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()
|
|
|
|
|
2022-10-10 20:52:26 +08:00
|
|
|
# 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")
|
2022-10-10 20:48:26 +08:00
|
|
|
assert len(record) == 1
|
|
|
|
|
|
|
|
|
|
|
|
def test_fixture_disallow_marks_on_fixtures():
|
|
|
|
"""Test that applying a mark to a fixture warns (#3364)."""
|
|
|
|
with pytest.warns(
|
2023-06-25 23:08:53 +08:00
|
|
|
pytest.PytestRemovedIn8Warning,
|
2022-10-10 20:48:26 +08:00
|
|
|
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()
|
|
|
|
|
2022-10-10 20:52:26 +08:00
|
|
|
assert len(record) == 2 # one for each mark decorator
|
|
|
|
|
|
|
|
|
|
|
|
def test_fixture_disallowed_between_marks():
|
|
|
|
"""Test that applying a mark to a fixture warns (#3364)."""
|
|
|
|
with pytest.warns(
|
2023-06-25 23:08:53 +08:00
|
|
|
pytest.PytestRemovedIn8Warning,
|
2022-10-10 20:52:26 +08:00
|
|
|
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
|
2022-10-10 20:55:24 +08:00
|
|
|
|
|
|
|
|
2022-10-10 04:16:33 +08:00
|
|
|
@pytest.mark.filterwarnings("default")
|
|
|
|
def test_nose_deprecated_with_setup(pytester: Pytester) -> None:
|
|
|
|
pytest.importorskip("nose")
|
|
|
|
pytester.makepyfile(
|
|
|
|
"""
|
|
|
|
from nose.tools import with_setup
|
|
|
|
|
|
|
|
def setup_fn_no_op():
|
|
|
|
...
|
|
|
|
|
|
|
|
def teardown_fn_no_op():
|
|
|
|
...
|
|
|
|
|
|
|
|
@with_setup(setup_fn_no_op, teardown_fn_no_op)
|
|
|
|
def test_omits_warnings():
|
|
|
|
...
|
|
|
|
"""
|
|
|
|
)
|
2023-06-23 19:36:48 +08:00
|
|
|
output = pytester.runpytest("-Wdefault::pytest.PytestRemovedIn8Warning")
|
2022-10-10 04:16:33 +08:00
|
|
|
message = [
|
|
|
|
"*PytestRemovedIn8Warning: Support for nose tests is deprecated and will be removed in a future release.",
|
|
|
|
"*test_nose_deprecated_with_setup.py::test_omits_warnings is using nose method: `setup_fn_no_op` (setup)",
|
|
|
|
"*PytestRemovedIn8Warning: Support for nose tests is deprecated and will be removed in a future release.",
|
|
|
|
"*test_nose_deprecated_with_setup.py::test_omits_warnings is using nose method: `teardown_fn_no_op` (teardown)",
|
|
|
|
]
|
|
|
|
output.stdout.fnmatch_lines(message)
|
|
|
|
output.assert_outcomes(passed=1)
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.mark.filterwarnings("default")
|
|
|
|
def test_nose_deprecated_setup_teardown(pytester: Pytester) -> None:
|
|
|
|
pytest.importorskip("nose")
|
|
|
|
pytester.makepyfile(
|
|
|
|
"""
|
|
|
|
class Test:
|
|
|
|
|
|
|
|
def setup(self):
|
|
|
|
...
|
|
|
|
|
|
|
|
def teardown(self):
|
|
|
|
...
|
|
|
|
|
|
|
|
def test(self):
|
|
|
|
...
|
|
|
|
"""
|
|
|
|
)
|
2023-06-23 19:36:48 +08:00
|
|
|
output = pytester.runpytest("-Wdefault::pytest.PytestRemovedIn8Warning")
|
2022-10-10 04:16:33 +08:00
|
|
|
message = [
|
|
|
|
"*PytestRemovedIn8Warning: Support for nose tests is deprecated and will be removed in a future release.",
|
|
|
|
"*test_nose_deprecated_setup_teardown.py::Test::test is using nose-specific method: `setup(self)`",
|
|
|
|
"*To remove this warning, rename it to `setup_method(self)`",
|
|
|
|
"*PytestRemovedIn8Warning: Support for nose tests is deprecated and will be removed in a future release.",
|
|
|
|
"*test_nose_deprecated_setup_teardown.py::Test::test is using nose-specific method: `teardown(self)`",
|
|
|
|
"*To remove this warning, rename it to `teardown_method(self)`",
|
|
|
|
]
|
|
|
|
output.stdout.fnmatch_lines(message)
|
|
|
|
output.assert_outcomes(passed=1)
|