2024-01-28 21:12:42 +08:00
|
|
|
# mypy: allow-untyped-defs
|
2019-11-23 02:18:07 +08:00
|
|
|
import os
|
2022-02-15 21:00:50 +08:00
|
|
|
import sys
|
2020-05-01 19:40:17 +08:00
|
|
|
from typing import List
|
|
|
|
from typing import Optional
|
|
|
|
from typing import Tuple
|
2024-02-01 04:12:33 +08:00
|
|
|
import warnings
|
2017-05-26 13:12:02 +08:00
|
|
|
|
2020-03-27 09:24:00 +08:00
|
|
|
from _pytest.fixtures import FixtureRequest
|
2020-12-06 17:20:33 +08:00
|
|
|
from _pytest.pytester import Pytester
|
2024-02-01 04:12:33 +08:00
|
|
|
import pytest
|
|
|
|
|
2016-11-21 18:26:43 +08:00
|
|
|
|
2018-05-23 22:48:46 +08:00
|
|
|
WARNINGS_SUMMARY_HEADER = "warnings summary"
|
2017-02-25 23:02:48 +08:00
|
|
|
|
2017-07-17 07:25:09 +08:00
|
|
|
|
2016-11-21 18:26:43 +08:00
|
|
|
@pytest.fixture
|
2020-12-06 17:20:33 +08:00
|
|
|
def pyfile_with_warnings(pytester: Pytester, request: FixtureRequest) -> str:
|
2020-07-18 17:35:13 +08:00
|
|
|
"""Create a test file which calls a function in a module which generates warnings."""
|
2020-12-06 17:20:33 +08:00
|
|
|
pytester.syspathinsert()
|
2024-02-03 04:21:39 +08:00
|
|
|
module_name = request.function.__name__[len("test_") :] + "_module"
|
2020-12-06 17:20:33 +08:00
|
|
|
test_file = pytester.makepyfile(
|
2024-02-01 04:12:33 +08:00
|
|
|
f"""
|
2020-03-27 09:24:00 +08:00
|
|
|
import {module_name}
|
|
|
|
def test_func():
|
|
|
|
assert {module_name}.foo() == 1
|
2024-02-01 04:12:33 +08:00
|
|
|
""",
|
2018-05-23 22:48:46 +08:00
|
|
|
**{
|
|
|
|
module_name: """
|
2017-03-05 07:53:42 +08:00
|
|
|
import warnings
|
|
|
|
def foo():
|
2017-05-30 05:59:34 +08:00
|
|
|
warnings.warn(UserWarning("user warning"))
|
|
|
|
warnings.warn(RuntimeWarning("runtime warning"))
|
2017-03-05 07:53:42 +08:00
|
|
|
return 1
|
2020-03-27 09:24:00 +08:00
|
|
|
""",
|
2020-03-27 20:54:20 +08:00
|
|
|
},
|
2018-05-23 22:48:46 +08:00
|
|
|
)
|
2020-03-27 09:24:00 +08:00
|
|
|
return str(test_file)
|
2016-11-21 18:26:43 +08:00
|
|
|
|
|
|
|
|
2021-05-04 20:27:21 +08:00
|
|
|
@pytest.mark.filterwarnings("default::UserWarning", "default::RuntimeWarning")
|
2020-12-06 17:20:33 +08:00
|
|
|
def test_normal_flow(pytester: Pytester, pyfile_with_warnings) -> None:
|
2020-07-18 17:35:13 +08:00
|
|
|
"""Check that the warnings section is displayed."""
|
2020-12-06 17:20:33 +08:00
|
|
|
result = pytester.runpytest(pyfile_with_warnings)
|
2018-05-23 22:48:46 +08:00
|
|
|
result.stdout.fnmatch_lines(
|
|
|
|
[
|
2024-05-01 00:06:26 +08:00
|
|
|
f"*== {WARNINGS_SUMMARY_HEADER} ==*",
|
2018-10-25 04:33:50 +08:00
|
|
|
"test_normal_flow.py::test_func",
|
2018-05-23 22:48:46 +08:00
|
|
|
"*normal_flow_module.py:3: UserWarning: user warning",
|
|
|
|
'* warnings.warn(UserWarning("user warning"))',
|
|
|
|
"*normal_flow_module.py:4: RuntimeWarning: runtime warning",
|
|
|
|
'* warnings.warn(RuntimeWarning("runtime warning"))',
|
|
|
|
"* 1 passed, 2 warnings*",
|
|
|
|
]
|
|
|
|
)
|
|
|
|
|
|
|
|
|
2021-05-04 20:27:21 +08:00
|
|
|
@pytest.mark.filterwarnings("always::UserWarning")
|
2020-12-06 17:20:33 +08:00
|
|
|
def test_setup_teardown_warnings(pytester: Pytester) -> None:
|
|
|
|
pytester.makepyfile(
|
2018-05-23 22:48:46 +08:00
|
|
|
"""
|
2017-03-05 03:07:37 +08:00
|
|
|
import warnings
|
|
|
|
import pytest
|
|
|
|
|
|
|
|
@pytest.fixture
|
|
|
|
def fix():
|
|
|
|
warnings.warn(UserWarning("warning during setup"))
|
|
|
|
yield
|
|
|
|
warnings.warn(UserWarning("warning during teardown"))
|
|
|
|
|
|
|
|
def test_func(fix):
|
|
|
|
pass
|
2018-05-23 22:48:46 +08:00
|
|
|
"""
|
|
|
|
)
|
2020-12-06 17:20:33 +08:00
|
|
|
result = pytester.runpytest()
|
2018-05-23 22:48:46 +08:00
|
|
|
result.stdout.fnmatch_lines(
|
|
|
|
[
|
2024-05-01 00:06:26 +08:00
|
|
|
f"*== {WARNINGS_SUMMARY_HEADER} ==*",
|
2018-05-23 22:48:46 +08:00
|
|
|
"*test_setup_teardown_warnings.py:6: UserWarning: warning during setup",
|
|
|
|
'*warnings.warn(UserWarning("warning during setup"))',
|
|
|
|
"*test_setup_teardown_warnings.py:8: UserWarning: warning during teardown",
|
|
|
|
'*warnings.warn(UserWarning("warning during teardown"))',
|
|
|
|
"* 1 passed, 2 warnings*",
|
|
|
|
]
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.mark.parametrize("method", ["cmdline", "ini"])
|
2020-12-06 17:20:33 +08:00
|
|
|
def test_as_errors(pytester: Pytester, pyfile_with_warnings, method) -> None:
|
2018-05-23 22:48:46 +08:00
|
|
|
args = ("-W", "error") if method == "cmdline" else ()
|
|
|
|
if method == "ini":
|
2020-12-06 17:20:33 +08:00
|
|
|
pytester.makeini(
|
2018-05-23 22:48:46 +08:00
|
|
|
"""
|
2016-11-21 18:26:43 +08:00
|
|
|
[pytest]
|
2019-03-24 18:17:55 +08:00
|
|
|
filterwarnings=error
|
2018-05-23 22:48:46 +08:00
|
|
|
"""
|
|
|
|
)
|
2019-03-24 18:17:55 +08:00
|
|
|
# Use a subprocess, since changing logging level affects other threads
|
|
|
|
# (xdist).
|
2020-12-06 17:20:33 +08:00
|
|
|
result = pytester.runpytest_subprocess(*args, pyfile_with_warnings)
|
2018-05-23 22:48:46 +08:00
|
|
|
result.stdout.fnmatch_lines(
|
|
|
|
[
|
|
|
|
"E UserWarning: user warning",
|
|
|
|
"as_errors_module.py:3: UserWarning",
|
|
|
|
"* 1 failed in *",
|
|
|
|
]
|
|
|
|
)
|
2016-11-21 18:26:43 +08:00
|
|
|
|
|
|
|
|
2018-05-23 22:48:46 +08:00
|
|
|
@pytest.mark.parametrize("method", ["cmdline", "ini"])
|
2020-12-06 17:20:33 +08:00
|
|
|
def test_ignore(pytester: Pytester, pyfile_with_warnings, method) -> None:
|
2018-05-23 22:48:46 +08:00
|
|
|
args = ("-W", "ignore") if method == "cmdline" else ()
|
|
|
|
if method == "ini":
|
2020-12-06 17:20:33 +08:00
|
|
|
pytester.makeini(
|
2018-05-23 22:48:46 +08:00
|
|
|
"""
|
2016-11-21 18:26:43 +08:00
|
|
|
[pytest]
|
|
|
|
filterwarnings= ignore
|
2018-05-23 22:48:46 +08:00
|
|
|
"""
|
|
|
|
)
|
2016-11-21 18:26:43 +08:00
|
|
|
|
2020-12-06 17:20:33 +08:00
|
|
|
result = pytester.runpytest(*args, pyfile_with_warnings)
|
2018-05-23 22:48:46 +08:00
|
|
|
result.stdout.fnmatch_lines(["* 1 passed in *"])
|
2017-02-25 23:02:48 +08:00
|
|
|
assert WARNINGS_SUMMARY_HEADER not in result.stdout.str()
|
2016-11-21 18:26:43 +08:00
|
|
|
|
2017-05-25 17:59:42 +08:00
|
|
|
|
2021-05-04 20:27:21 +08:00
|
|
|
@pytest.mark.filterwarnings("always::UserWarning")
|
2020-12-06 17:20:33 +08:00
|
|
|
def test_unicode(pytester: Pytester) -> None:
|
|
|
|
pytester.makepyfile(
|
2020-03-27 09:24:00 +08:00
|
|
|
"""
|
2017-05-25 17:59:42 +08:00
|
|
|
import warnings
|
|
|
|
import pytest
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.fixture
|
|
|
|
def fix():
|
2019-06-05 08:48:06 +08:00
|
|
|
warnings.warn("测试")
|
2017-05-25 17:59:42 +08:00
|
|
|
yield
|
|
|
|
|
|
|
|
def test_func(fix):
|
|
|
|
pass
|
2019-06-03 06:40:34 +08:00
|
|
|
"""
|
2018-05-23 22:48:46 +08:00
|
|
|
)
|
2020-12-06 17:20:33 +08:00
|
|
|
result = pytester.runpytest()
|
2018-05-23 22:48:46 +08:00
|
|
|
result.stdout.fnmatch_lines(
|
|
|
|
[
|
2024-05-01 00:06:26 +08:00
|
|
|
f"*== {WARNINGS_SUMMARY_HEADER} ==*",
|
2019-06-03 06:59:44 +08:00
|
|
|
"*test_unicode.py:7: UserWarning: \u6d4b\u8bd5*",
|
2019-10-27 23:02:37 +08:00
|
|
|
"* 1 passed, 1 warning*",
|
2018-05-23 22:48:46 +08:00
|
|
|
]
|
|
|
|
)
|
|
|
|
|
|
|
|
|
2020-12-06 17:20:33 +08:00
|
|
|
def test_works_with_filterwarnings(pytester: Pytester) -> None:
|
2017-05-30 05:59:34 +08:00
|
|
|
"""Ensure our warnings capture does not mess with pre-installed filters (#2430)."""
|
2020-12-06 17:20:33 +08:00
|
|
|
pytester.makepyfile(
|
2018-05-23 22:48:46 +08:00
|
|
|
"""
|
2017-05-30 05:59:34 +08:00
|
|
|
import warnings
|
|
|
|
|
|
|
|
class MyWarning(Warning):
|
|
|
|
pass
|
2017-07-17 07:25:06 +08:00
|
|
|
|
2017-05-30 05:59:34 +08:00
|
|
|
warnings.filterwarnings("error", category=MyWarning)
|
2017-07-17 07:25:06 +08:00
|
|
|
|
2017-05-30 05:59:34 +08:00
|
|
|
class TestWarnings(object):
|
|
|
|
def test_my_warning(self):
|
|
|
|
try:
|
|
|
|
warnings.warn(MyWarning("warn!"))
|
|
|
|
assert False
|
|
|
|
except MyWarning:
|
|
|
|
assert True
|
2018-05-23 22:48:46 +08:00
|
|
|
"""
|
|
|
|
)
|
2020-12-06 17:20:33 +08:00
|
|
|
result = pytester.runpytest()
|
2018-05-23 22:48:46 +08:00
|
|
|
result.stdout.fnmatch_lines(["*== 1 passed in *"])
|
2017-07-21 09:02:21 +08:00
|
|
|
|
|
|
|
|
2018-05-23 22:48:46 +08:00
|
|
|
@pytest.mark.parametrize("default_config", ["ini", "cmdline"])
|
2020-12-06 17:20:33 +08:00
|
|
|
def test_filterwarnings_mark(pytester: Pytester, default_config) -> None:
|
2020-07-18 17:35:13 +08:00
|
|
|
"""Test ``filterwarnings`` mark works and takes precedence over command
|
|
|
|
line and ini options."""
|
2018-05-23 22:48:46 +08:00
|
|
|
if default_config == "ini":
|
2020-12-06 17:20:33 +08:00
|
|
|
pytester.makeini(
|
2018-05-23 22:48:46 +08:00
|
|
|
"""
|
2017-07-21 09:02:21 +08:00
|
|
|
[pytest]
|
2021-05-04 20:27:21 +08:00
|
|
|
filterwarnings = always::RuntimeWarning
|
2018-05-23 22:48:46 +08:00
|
|
|
"""
|
|
|
|
)
|
2020-12-06 17:20:33 +08:00
|
|
|
pytester.makepyfile(
|
2018-05-23 22:48:46 +08:00
|
|
|
"""
|
2017-07-21 09:02:21 +08:00
|
|
|
import warnings
|
|
|
|
import pytest
|
|
|
|
|
|
|
|
@pytest.mark.filterwarnings('ignore::RuntimeWarning')
|
|
|
|
def test_ignore_runtime_warning():
|
|
|
|
warnings.warn(RuntimeWarning())
|
|
|
|
|
|
|
|
@pytest.mark.filterwarnings('error')
|
|
|
|
def test_warning_error():
|
|
|
|
warnings.warn(RuntimeWarning())
|
|
|
|
|
|
|
|
def test_show_warning():
|
|
|
|
warnings.warn(RuntimeWarning())
|
2018-05-23 22:48:46 +08:00
|
|
|
"""
|
|
|
|
)
|
2021-05-04 20:27:21 +08:00
|
|
|
result = pytester.runpytest(
|
|
|
|
"-W always::RuntimeWarning" if default_config == "cmdline" else ""
|
|
|
|
)
|
2019-10-27 23:02:37 +08:00
|
|
|
result.stdout.fnmatch_lines(["*= 1 failed, 2 passed, 1 warning in *"])
|
2017-11-28 09:07:29 +08:00
|
|
|
|
|
|
|
|
2020-12-06 17:20:33 +08:00
|
|
|
def test_non_string_warning_argument(pytester: Pytester) -> None:
|
2017-11-28 09:07:29 +08:00
|
|
|
"""Non-str argument passed to warning breaks pytest (#2956)"""
|
2020-12-06 17:20:33 +08:00
|
|
|
pytester.makepyfile(
|
2019-06-05 08:48:06 +08:00
|
|
|
"""\
|
2017-11-28 09:07:29 +08:00
|
|
|
import warnings
|
|
|
|
import pytest
|
|
|
|
|
|
|
|
def test():
|
2019-06-05 08:48:06 +08:00
|
|
|
warnings.warn(UserWarning(1, 'foo'))
|
|
|
|
"""
|
2018-05-23 22:48:46 +08:00
|
|
|
)
|
2021-05-04 20:27:21 +08:00
|
|
|
result = pytester.runpytest("-W", "always::UserWarning")
|
2019-10-27 23:02:37 +08:00
|
|
|
result.stdout.fnmatch_lines(["*= 1 passed, 1 warning in *"])
|
2018-08-15 05:07:29 +08:00
|
|
|
|
|
|
|
|
2020-12-06 17:20:33 +08:00
|
|
|
def test_filterwarnings_mark_registration(pytester: Pytester) -> None:
|
2018-08-15 05:07:29 +08:00
|
|
|
"""Ensure filterwarnings mark is registered"""
|
2020-12-06 17:20:33 +08:00
|
|
|
pytester.makepyfile(
|
2018-08-15 05:07:29 +08:00
|
|
|
"""
|
|
|
|
import pytest
|
|
|
|
|
|
|
|
@pytest.mark.filterwarnings('error')
|
2018-08-15 09:29:42 +08:00
|
|
|
def test_func():
|
|
|
|
pass
|
2018-08-15 05:07:29 +08:00
|
|
|
"""
|
|
|
|
)
|
2020-12-06 17:20:33 +08:00
|
|
|
result = pytester.runpytest("--strict-markers")
|
2018-08-15 05:07:29 +08:00
|
|
|
assert result.ret == 0
|
2018-08-26 07:41:16 +08:00
|
|
|
|
|
|
|
|
2021-05-04 20:27:21 +08:00
|
|
|
@pytest.mark.filterwarnings("always::UserWarning")
|
2021-12-08 04:00:31 +08:00
|
|
|
def test_warning_recorded_hook(pytester: Pytester) -> None:
|
2020-12-06 17:20:33 +08:00
|
|
|
pytester.makeconftest(
|
2018-09-05 02:22:07 +08:00
|
|
|
"""
|
|
|
|
def pytest_configure(config):
|
2020-09-04 22:57:15 +08:00
|
|
|
config.issue_config_time_warning(UserWarning("config warning"), stacklevel=2)
|
2018-09-05 02:22:07 +08:00
|
|
|
"""
|
|
|
|
)
|
2020-12-06 17:20:33 +08:00
|
|
|
pytester.makepyfile(
|
2018-09-05 02:22:07 +08:00
|
|
|
"""
|
|
|
|
import pytest, warnings
|
|
|
|
|
|
|
|
warnings.warn(UserWarning("collect warning"))
|
|
|
|
|
|
|
|
@pytest.fixture
|
|
|
|
def fix():
|
|
|
|
warnings.warn(UserWarning("setup warning"))
|
|
|
|
yield 1
|
|
|
|
warnings.warn(UserWarning("teardown warning"))
|
|
|
|
|
|
|
|
def test_func(fix):
|
|
|
|
warnings.warn(UserWarning("call warning"))
|
|
|
|
assert fix == 1
|
|
|
|
"""
|
|
|
|
)
|
2018-08-26 07:41:16 +08:00
|
|
|
|
|
|
|
collected = []
|
|
|
|
|
|
|
|
class WarningCollector:
|
2020-05-27 12:53:31 +08:00
|
|
|
def pytest_warning_recorded(self, warning_message, when, nodeid, location):
|
|
|
|
collected.append((str(warning_message.message), when, nodeid, location))
|
2018-08-26 07:41:16 +08:00
|
|
|
|
2020-12-06 17:20:33 +08:00
|
|
|
result = pytester.runpytest(plugins=[WarningCollector()])
|
2018-08-26 07:41:16 +08:00
|
|
|
result.stdout.fnmatch_lines(["*1 passed*"])
|
|
|
|
|
|
|
|
expected = [
|
2020-05-28 12:02:28 +08:00
|
|
|
("config warning", "config", ""),
|
2020-05-28 11:03:07 +08:00
|
|
|
("collect warning", "collect", ""),
|
2021-12-08 04:00:31 +08:00
|
|
|
("setup warning", "runtest", "test_warning_recorded_hook.py::test_func"),
|
|
|
|
("call warning", "runtest", "test_warning_recorded_hook.py::test_func"),
|
|
|
|
("teardown warning", "runtest", "test_warning_recorded_hook.py::test_func"),
|
2018-08-26 07:41:16 +08:00
|
|
|
]
|
2020-05-27 12:53:31 +08:00
|
|
|
for index in range(len(expected)):
|
|
|
|
collected_result = collected[index]
|
|
|
|
expected_result = expected[index]
|
|
|
|
|
|
|
|
assert collected_result[0] == expected_result[0], str(collected)
|
|
|
|
assert collected_result[1] == expected_result[1], str(collected)
|
|
|
|
assert collected_result[2] == expected_result[2], str(collected)
|
|
|
|
|
2020-05-28 11:03:07 +08:00
|
|
|
# NOTE: collected_result[3] is location, which differs based on the platform you are on
|
2021-12-27 20:23:15 +08:00
|
|
|
# thus, the best we can do here is assert the types of the parameters match what we expect
|
2020-05-28 11:03:07 +08:00
|
|
|
# and not try and preload it in the expected array
|
|
|
|
if collected_result[3] is not None:
|
|
|
|
assert type(collected_result[3][0]) is str, str(collected)
|
|
|
|
assert type(collected_result[3][1]) is int, str(collected)
|
|
|
|
assert type(collected_result[3][2]) is str, str(collected)
|
2020-05-27 12:53:31 +08:00
|
|
|
else:
|
2020-05-28 11:03:07 +08:00
|
|
|
assert collected_result[3] is None, str(collected)
|
2018-08-26 22:09:54 +08:00
|
|
|
|
|
|
|
|
2021-05-04 20:27:21 +08:00
|
|
|
@pytest.mark.filterwarnings("always::UserWarning")
|
2020-12-06 17:20:33 +08:00
|
|
|
def test_collection_warnings(pytester: Pytester) -> None:
|
2020-07-18 17:35:13 +08:00
|
|
|
"""Check that we also capture warnings issued during test collection (#3251)."""
|
2020-12-06 17:20:33 +08:00
|
|
|
pytester.makepyfile(
|
2018-08-26 22:09:54 +08:00
|
|
|
"""
|
|
|
|
import warnings
|
|
|
|
|
|
|
|
warnings.warn(UserWarning("collection warning"))
|
|
|
|
|
|
|
|
def test_foo():
|
|
|
|
pass
|
|
|
|
"""
|
|
|
|
)
|
2020-12-06 17:20:33 +08:00
|
|
|
result = pytester.runpytest()
|
2018-08-26 22:09:54 +08:00
|
|
|
result.stdout.fnmatch_lines(
|
|
|
|
[
|
2024-05-01 00:06:26 +08:00
|
|
|
f"*== {WARNINGS_SUMMARY_HEADER} ==*",
|
2018-10-25 04:33:50 +08:00
|
|
|
" *collection_warnings.py:3: UserWarning: collection warning",
|
|
|
|
' warnings.warn(UserWarning("collection warning"))',
|
2019-10-27 23:02:37 +08:00
|
|
|
"* 1 passed, 1 warning*",
|
2018-08-26 22:09:54 +08:00
|
|
|
]
|
|
|
|
)
|
2018-09-04 04:52:44 +08:00
|
|
|
|
|
|
|
|
2021-05-04 20:27:21 +08:00
|
|
|
@pytest.mark.filterwarnings("always::UserWarning")
|
2020-12-06 17:20:33 +08:00
|
|
|
def test_mark_regex_escape(pytester: Pytester) -> None:
|
2018-09-05 21:20:25 +08:00
|
|
|
"""@pytest.mark.filterwarnings should not try to escape regex characters (#3936)"""
|
2020-12-06 17:20:33 +08:00
|
|
|
pytester.makepyfile(
|
2018-09-05 21:20:25 +08:00
|
|
|
r"""
|
|
|
|
import pytest, warnings
|
|
|
|
|
|
|
|
@pytest.mark.filterwarnings(r"ignore:some \(warning\)")
|
|
|
|
def test_foo():
|
|
|
|
warnings.warn(UserWarning("some (warning)"))
|
|
|
|
"""
|
|
|
|
)
|
2020-12-06 17:20:33 +08:00
|
|
|
result = pytester.runpytest()
|
2018-09-05 21:20:25 +08:00
|
|
|
assert WARNINGS_SUMMARY_HEADER not in result.stdout.str()
|
|
|
|
|
|
|
|
|
2021-05-04 20:27:21 +08:00
|
|
|
@pytest.mark.filterwarnings("default::pytest.PytestWarning")
|
2018-09-04 04:56:18 +08:00
|
|
|
@pytest.mark.parametrize("ignore_pytest_warnings", ["no", "ini", "cmdline"])
|
2020-12-06 17:20:33 +08:00
|
|
|
def test_hide_pytest_internal_warnings(
|
|
|
|
pytester: Pytester, ignore_pytest_warnings
|
|
|
|
) -> None:
|
2018-09-04 04:56:18 +08:00
|
|
|
"""Make sure we can ignore internal pytest warnings using a warnings filter."""
|
2020-12-06 17:20:33 +08:00
|
|
|
pytester.makepyfile(
|
2018-09-04 04:56:18 +08:00
|
|
|
"""
|
|
|
|
import pytest
|
|
|
|
import warnings
|
|
|
|
|
|
|
|
warnings.warn(pytest.PytestWarning("some internal warning"))
|
|
|
|
|
|
|
|
def test_bar():
|
|
|
|
pass
|
|
|
|
"""
|
|
|
|
)
|
|
|
|
if ignore_pytest_warnings == "ini":
|
2020-12-06 17:20:33 +08:00
|
|
|
pytester.makeini(
|
2018-09-04 04:56:18 +08:00
|
|
|
"""
|
|
|
|
[pytest]
|
|
|
|
filterwarnings = ignore::pytest.PytestWarning
|
|
|
|
"""
|
|
|
|
)
|
|
|
|
args = (
|
|
|
|
["-W", "ignore::pytest.PytestWarning"]
|
|
|
|
if ignore_pytest_warnings == "cmdline"
|
|
|
|
else []
|
|
|
|
)
|
2020-12-06 17:20:33 +08:00
|
|
|
result = pytester.runpytest(*args)
|
2018-09-04 04:56:18 +08:00
|
|
|
if ignore_pytest_warnings != "no":
|
|
|
|
assert WARNINGS_SUMMARY_HEADER not in result.stdout.str()
|
|
|
|
else:
|
|
|
|
result.stdout.fnmatch_lines(
|
|
|
|
[
|
2024-05-01 00:06:26 +08:00
|
|
|
f"*== {WARNINGS_SUMMARY_HEADER} ==*",
|
2018-09-04 04:56:18 +08:00
|
|
|
"*test_hide_pytest_internal_warnings.py:4: PytestWarning: some internal warning",
|
2019-10-27 23:02:37 +08:00
|
|
|
"* 1 passed, 1 warning *",
|
2018-09-04 04:56:18 +08:00
|
|
|
]
|
|
|
|
)
|
|
|
|
|
|
|
|
|
2018-09-07 05:02:36 +08:00
|
|
|
@pytest.mark.parametrize("ignore_on_cmdline", [True, False])
|
2020-12-06 17:20:33 +08:00
|
|
|
def test_option_precedence_cmdline_over_ini(
|
|
|
|
pytester: Pytester, ignore_on_cmdline
|
|
|
|
) -> None:
|
2020-07-18 17:35:13 +08:00
|
|
|
"""Filters defined in the command-line should take precedence over filters in ini files (#3946)."""
|
2020-12-06 17:20:33 +08:00
|
|
|
pytester.makeini(
|
2018-09-07 05:02:36 +08:00
|
|
|
"""
|
|
|
|
[pytest]
|
2021-05-04 20:27:21 +08:00
|
|
|
filterwarnings = error::UserWarning
|
2018-09-07 05:02:36 +08:00
|
|
|
"""
|
|
|
|
)
|
2020-12-06 17:20:33 +08:00
|
|
|
pytester.makepyfile(
|
2018-09-07 05:02:36 +08:00
|
|
|
"""
|
|
|
|
import warnings
|
|
|
|
def test():
|
|
|
|
warnings.warn(UserWarning('hello'))
|
|
|
|
"""
|
|
|
|
)
|
|
|
|
args = ["-W", "ignore"] if ignore_on_cmdline else []
|
2020-12-06 17:20:33 +08:00
|
|
|
result = pytester.runpytest(*args)
|
2018-09-07 05:02:36 +08:00
|
|
|
if ignore_on_cmdline:
|
|
|
|
result.stdout.fnmatch_lines(["* 1 passed in*"])
|
|
|
|
else:
|
|
|
|
result.stdout.fnmatch_lines(["* 1 failed in*"])
|
|
|
|
|
|
|
|
|
2020-12-06 17:20:33 +08:00
|
|
|
def test_option_precedence_mark(pytester: Pytester) -> None:
|
2018-09-07 05:02:36 +08:00
|
|
|
"""Filters defined by marks should always take precedence (#3946)."""
|
2020-12-06 17:20:33 +08:00
|
|
|
pytester.makeini(
|
2018-09-07 05:02:36 +08:00
|
|
|
"""
|
|
|
|
[pytest]
|
|
|
|
filterwarnings = ignore
|
|
|
|
"""
|
|
|
|
)
|
2020-12-06 17:20:33 +08:00
|
|
|
pytester.makepyfile(
|
2018-09-07 05:02:36 +08:00
|
|
|
"""
|
|
|
|
import pytest, warnings
|
|
|
|
@pytest.mark.filterwarnings('error')
|
|
|
|
def test():
|
|
|
|
warnings.warn(UserWarning('hello'))
|
|
|
|
"""
|
|
|
|
)
|
2020-12-06 17:20:33 +08:00
|
|
|
result = pytester.runpytest("-W", "ignore")
|
2018-09-07 05:02:36 +08:00
|
|
|
result.stdout.fnmatch_lines(["* 1 failed in*"])
|
|
|
|
|
|
|
|
|
2018-09-04 04:52:44 +08:00
|
|
|
class TestDeprecationWarningsByDefault:
|
|
|
|
"""
|
|
|
|
Note: all pytest runs are executed in a subprocess so we don't inherit warning filters
|
|
|
|
from pytest's own test suite
|
|
|
|
"""
|
|
|
|
|
2020-12-06 17:20:33 +08:00
|
|
|
def create_file(self, pytester: Pytester, mark="") -> None:
|
|
|
|
pytester.makepyfile(
|
2024-02-01 04:12:33 +08:00
|
|
|
f"""
|
2018-09-04 04:52:44 +08:00
|
|
|
import pytest, warnings
|
|
|
|
|
|
|
|
warnings.warn(DeprecationWarning("collection"))
|
|
|
|
|
|
|
|
{mark}
|
|
|
|
def test_foo():
|
|
|
|
warnings.warn(PendingDeprecationWarning("test run"))
|
2024-02-01 04:12:33 +08:00
|
|
|
"""
|
2018-09-04 04:52:44 +08:00
|
|
|
)
|
|
|
|
|
2018-09-22 19:27:53 +08:00
|
|
|
@pytest.mark.parametrize("customize_filters", [True, False])
|
2020-12-06 17:20:33 +08:00
|
|
|
def test_shown_by_default(self, pytester: Pytester, customize_filters) -> None:
|
2018-09-22 19:27:53 +08:00
|
|
|
"""Show deprecation warnings by default, even if user has customized the warnings filters (#4013)."""
|
2020-12-06 17:20:33 +08:00
|
|
|
self.create_file(pytester)
|
2018-09-22 19:27:53 +08:00
|
|
|
if customize_filters:
|
2020-12-06 17:20:33 +08:00
|
|
|
pytester.makeini(
|
2018-09-22 19:27:53 +08:00
|
|
|
"""
|
|
|
|
[pytest]
|
|
|
|
filterwarnings =
|
|
|
|
once::UserWarning
|
|
|
|
"""
|
|
|
|
)
|
2020-12-06 17:20:33 +08:00
|
|
|
result = pytester.runpytest_subprocess()
|
2018-09-04 04:52:44 +08:00
|
|
|
result.stdout.fnmatch_lines(
|
|
|
|
[
|
2024-05-01 00:06:26 +08:00
|
|
|
f"*== {WARNINGS_SUMMARY_HEADER} ==*",
|
2018-09-04 04:52:44 +08:00
|
|
|
"*test_shown_by_default.py:3: DeprecationWarning: collection",
|
|
|
|
"*test_shown_by_default.py:7: PendingDeprecationWarning: test run",
|
|
|
|
"* 1 passed, 2 warnings*",
|
|
|
|
]
|
|
|
|
)
|
|
|
|
|
2020-12-06 17:20:33 +08:00
|
|
|
def test_hidden_by_ini(self, pytester: Pytester) -> None:
|
|
|
|
self.create_file(pytester)
|
|
|
|
pytester.makeini(
|
2018-09-04 04:52:44 +08:00
|
|
|
"""
|
|
|
|
[pytest]
|
2018-09-22 19:27:53 +08:00
|
|
|
filterwarnings =
|
|
|
|
ignore::DeprecationWarning
|
|
|
|
ignore::PendingDeprecationWarning
|
2018-09-04 04:52:44 +08:00
|
|
|
"""
|
|
|
|
)
|
2020-12-06 17:20:33 +08:00
|
|
|
result = pytester.runpytest_subprocess()
|
2018-09-04 04:52:44 +08:00
|
|
|
assert WARNINGS_SUMMARY_HEADER not in result.stdout.str()
|
|
|
|
|
2020-12-06 17:20:33 +08:00
|
|
|
def test_hidden_by_mark(self, pytester: Pytester) -> None:
|
2018-09-04 04:52:44 +08:00
|
|
|
"""Should hide the deprecation warning from the function, but the warning during collection should
|
|
|
|
be displayed normally.
|
|
|
|
"""
|
|
|
|
self.create_file(
|
2020-12-06 17:20:33 +08:00
|
|
|
pytester,
|
2018-09-22 19:27:53 +08:00
|
|
|
mark='@pytest.mark.filterwarnings("ignore::PendingDeprecationWarning")',
|
2018-09-04 04:52:44 +08:00
|
|
|
)
|
2020-12-06 17:20:33 +08:00
|
|
|
result = pytester.runpytest_subprocess()
|
2018-09-04 04:52:44 +08:00
|
|
|
result.stdout.fnmatch_lines(
|
|
|
|
[
|
2024-05-01 00:06:26 +08:00
|
|
|
f"*== {WARNINGS_SUMMARY_HEADER} ==*",
|
2018-09-04 04:52:44 +08:00
|
|
|
"*test_hidden_by_mark.py:3: DeprecationWarning: collection",
|
2019-10-27 23:02:37 +08:00
|
|
|
"* 1 passed, 1 warning*",
|
2018-09-04 04:52:44 +08:00
|
|
|
]
|
|
|
|
)
|
|
|
|
|
2020-12-06 17:20:33 +08:00
|
|
|
def test_hidden_by_cmdline(self, pytester: Pytester) -> None:
|
|
|
|
self.create_file(pytester)
|
|
|
|
result = pytester.runpytest_subprocess(
|
2018-09-22 19:27:53 +08:00
|
|
|
"-W",
|
|
|
|
"ignore::DeprecationWarning",
|
|
|
|
"-W",
|
|
|
|
"ignore::PendingDeprecationWarning",
|
|
|
|
)
|
2018-09-04 04:52:44 +08:00
|
|
|
assert WARNINGS_SUMMARY_HEADER not in result.stdout.str()
|
|
|
|
|
2020-12-06 17:20:33 +08:00
|
|
|
def test_hidden_by_system(self, pytester: Pytester, monkeypatch) -> None:
|
|
|
|
self.create_file(pytester)
|
2019-06-03 06:32:00 +08:00
|
|
|
monkeypatch.setenv("PYTHONWARNINGS", "once::UserWarning")
|
2020-12-06 17:20:33 +08:00
|
|
|
result = pytester.runpytest_subprocess()
|
2018-09-04 04:52:44 +08:00
|
|
|
assert WARNINGS_SUMMARY_HEADER not in result.stdout.str()
|
2018-10-19 06:42:25 +08:00
|
|
|
|
|
|
|
|
2024-01-02 18:21:08 +08:00
|
|
|
@pytest.mark.skip("not relevant until pytest 9.0")
|
2018-11-09 06:14:58 +08:00
|
|
|
@pytest.mark.parametrize("change_default", [None, "ini", "cmdline"])
|
2021-11-15 05:39:56 +08:00
|
|
|
def test_removed_in_x_warning_as_error(pytester: Pytester, change_default) -> None:
|
|
|
|
"""This ensures that PytestRemovedInXWarnings raised by pytest are turned into errors.
|
2019-06-30 23:56:27 +08:00
|
|
|
|
|
|
|
This test should be enabled as part of each major release, and skipped again afterwards
|
|
|
|
to ensure our deprecations are turning into warnings as expected.
|
|
|
|
"""
|
2020-12-06 17:20:33 +08:00
|
|
|
pytester.makepyfile(
|
2019-06-06 06:02:52 +08:00
|
|
|
"""
|
|
|
|
import warnings, pytest
|
|
|
|
def test():
|
2024-01-02 18:21:08 +08:00
|
|
|
warnings.warn(pytest.PytestRemovedIn9Warning("some warning"))
|
2019-06-06 06:02:52 +08:00
|
|
|
"""
|
|
|
|
)
|
|
|
|
if change_default == "ini":
|
2020-12-06 17:20:33 +08:00
|
|
|
pytester.makeini(
|
2019-06-06 06:02:52 +08:00
|
|
|
"""
|
|
|
|
[pytest]
|
|
|
|
filterwarnings =
|
2024-01-02 18:21:08 +08:00
|
|
|
ignore::pytest.PytestRemovedIn9Warning
|
2019-06-06 06:02:52 +08:00
|
|
|
"""
|
|
|
|
)
|
|
|
|
|
|
|
|
args = (
|
2024-01-02 18:21:08 +08:00
|
|
|
("-Wignore::pytest.PytestRemovedIn9Warning",)
|
2019-06-06 06:02:52 +08:00
|
|
|
if change_default == "cmdline"
|
|
|
|
else ()
|
|
|
|
)
|
2020-12-06 17:20:33 +08:00
|
|
|
result = pytester.runpytest(*args)
|
2019-06-06 06:02:52 +08:00
|
|
|
if change_default is None:
|
|
|
|
result.stdout.fnmatch_lines(["* 1 failed in *"])
|
|
|
|
else:
|
|
|
|
assert change_default in ("ini", "cmdline")
|
|
|
|
result.stdout.fnmatch_lines(["* 1 passed in *"])
|
|
|
|
|
|
|
|
|
2018-10-15 00:13:00 +08:00
|
|
|
class TestAssertionWarnings:
|
2018-10-15 15:53:27 +08:00
|
|
|
@staticmethod
|
2020-12-06 17:20:33 +08:00
|
|
|
def assert_result_warns(result, msg) -> None:
|
2024-05-01 00:06:26 +08:00
|
|
|
result.stdout.fnmatch_lines([f"*PytestAssertRewriteWarning: {msg}*"])
|
2018-10-15 15:53:27 +08:00
|
|
|
|
2020-12-06 17:20:33 +08:00
|
|
|
def test_tuple_warning(self, pytester: Pytester) -> None:
|
|
|
|
pytester.makepyfile(
|
2019-11-20 00:24:08 +08:00
|
|
|
"""\
|
2018-10-15 00:13:00 +08:00
|
|
|
def test_foo():
|
|
|
|
assert (1,2)
|
|
|
|
"""
|
|
|
|
)
|
2020-12-06 17:20:33 +08:00
|
|
|
result = pytester.runpytest()
|
2018-12-06 02:22:44 +08:00
|
|
|
self.assert_result_warns(
|
|
|
|
result, "assertion is always true, perhaps remove parentheses?"
|
|
|
|
)
|
2018-10-15 00:13:00 +08:00
|
|
|
|
2019-01-09 19:31:26 +08:00
|
|
|
|
2020-12-06 17:20:33 +08:00
|
|
|
def test_warnings_checker_twice() -> None:
|
2019-01-09 19:31:26 +08:00
|
|
|
"""Issue #4617"""
|
2019-01-10 04:58:51 +08:00
|
|
|
expectation = pytest.warns(UserWarning)
|
|
|
|
with expectation:
|
|
|
|
warnings.warn("Message A", UserWarning)
|
|
|
|
with expectation:
|
|
|
|
warnings.warn("Message B", UserWarning)
|
2019-01-23 05:42:22 +08:00
|
|
|
|
|
|
|
|
2021-05-04 20:27:21 +08:00
|
|
|
@pytest.mark.filterwarnings("always::UserWarning")
|
2020-12-06 17:20:33 +08:00
|
|
|
def test_group_warnings_by_message(pytester: Pytester) -> None:
|
|
|
|
pytester.copy_example("warnings/test_group_warnings_by_message.py")
|
|
|
|
result = pytester.runpytest()
|
2019-01-23 05:42:22 +08:00
|
|
|
result.stdout.fnmatch_lines(
|
|
|
|
[
|
2024-05-01 00:06:26 +08:00
|
|
|
f"*== {WARNINGS_SUMMARY_HEADER} ==*",
|
2020-04-05 22:10:05 +08:00
|
|
|
"test_group_warnings_by_message.py::test_foo[[]0[]]",
|
|
|
|
"test_group_warnings_by_message.py::test_foo[[]1[]]",
|
|
|
|
"test_group_warnings_by_message.py::test_foo[[]2[]]",
|
|
|
|
"test_group_warnings_by_message.py::test_foo[[]3[]]",
|
|
|
|
"test_group_warnings_by_message.py::test_foo[[]4[]]",
|
|
|
|
"test_group_warnings_by_message.py::test_foo_1",
|
|
|
|
" */test_group_warnings_by_message.py:*: UserWarning: foo",
|
|
|
|
" warnings.warn(UserWarning(msg))",
|
|
|
|
"",
|
|
|
|
"test_group_warnings_by_message.py::test_bar[[]0[]]",
|
|
|
|
"test_group_warnings_by_message.py::test_bar[[]1[]]",
|
|
|
|
"test_group_warnings_by_message.py::test_bar[[]2[]]",
|
|
|
|
"test_group_warnings_by_message.py::test_bar[[]3[]]",
|
|
|
|
"test_group_warnings_by_message.py::test_bar[[]4[]]",
|
|
|
|
" */test_group_warnings_by_message.py:*: UserWarning: bar",
|
|
|
|
" warnings.warn(UserWarning(msg))",
|
|
|
|
"",
|
|
|
|
"-- Docs: *",
|
|
|
|
"*= 11 passed, 11 warnings *",
|
|
|
|
],
|
|
|
|
consecutive=True,
|
2019-01-23 05:42:22 +08:00
|
|
|
)
|
2019-08-12 13:47:40 +08:00
|
|
|
|
|
|
|
|
2021-05-04 20:27:21 +08:00
|
|
|
@pytest.mark.filterwarnings("always::UserWarning")
|
2020-12-06 17:20:33 +08:00
|
|
|
def test_group_warnings_by_message_summary(pytester: Pytester) -> None:
|
|
|
|
pytester.copy_example("warnings/test_group_warnings_by_message_summary")
|
|
|
|
pytester.syspathinsert()
|
|
|
|
result = pytester.runpytest()
|
2020-02-28 17:33:59 +08:00
|
|
|
result.stdout.fnmatch_lines(
|
|
|
|
[
|
2024-05-01 00:06:26 +08:00
|
|
|
f"*== {WARNINGS_SUMMARY_HEADER} ==*",
|
2020-04-05 22:10:05 +08:00
|
|
|
"test_1.py: 21 warnings",
|
|
|
|
"test_2.py: 1 warning",
|
2024-01-28 21:12:42 +08:00
|
|
|
" */test_1.py:8: UserWarning: foo",
|
2020-04-05 22:10:05 +08:00
|
|
|
" warnings.warn(UserWarning(msg))",
|
|
|
|
"",
|
|
|
|
"test_1.py: 20 warnings",
|
2024-01-28 21:12:42 +08:00
|
|
|
" */test_1.py:8: UserWarning: bar",
|
2020-04-05 22:10:05 +08:00
|
|
|
" warnings.warn(UserWarning(msg))",
|
|
|
|
"",
|
|
|
|
"-- Docs: *",
|
|
|
|
"*= 42 passed, 42 warnings *",
|
2020-02-28 17:33:59 +08:00
|
|
|
],
|
|
|
|
consecutive=True,
|
|
|
|
)
|
|
|
|
|
|
|
|
|
2020-12-06 17:20:33 +08:00
|
|
|
def test_pytest_configure_warning(pytester: Pytester, recwarn) -> None:
|
2019-08-12 13:47:40 +08:00
|
|
|
"""Issue 5115."""
|
2020-12-06 17:20:33 +08:00
|
|
|
pytester.makeconftest(
|
2019-08-12 13:47:40 +08:00
|
|
|
"""
|
|
|
|
def pytest_configure():
|
|
|
|
import warnings
|
|
|
|
|
|
|
|
warnings.warn("from pytest_configure")
|
|
|
|
"""
|
|
|
|
)
|
|
|
|
|
2020-12-06 17:20:33 +08:00
|
|
|
result = pytester.runpytest()
|
2019-08-12 13:47:40 +08:00
|
|
|
assert result.ret == 5
|
|
|
|
assert "INTERNALERROR" not in result.stderr.str()
|
|
|
|
warning = recwarn.pop()
|
|
|
|
assert str(warning.message) == "from pytest_configure"
|
2019-11-23 02:18:07 +08:00
|
|
|
|
|
|
|
|
|
|
|
class TestStackLevel:
|
|
|
|
@pytest.fixture
|
2020-12-06 17:20:33 +08:00
|
|
|
def capwarn(self, pytester: Pytester):
|
2019-11-23 02:18:07 +08:00
|
|
|
class CapturedWarnings:
|
2020-10-06 09:13:05 +08:00
|
|
|
captured: List[
|
|
|
|
Tuple[warnings.WarningMessage, Optional[Tuple[str, int, str]]]
|
2020-12-30 17:56:09 +08:00
|
|
|
] = []
|
2019-11-23 02:18:07 +08:00
|
|
|
|
|
|
|
@classmethod
|
2020-05-25 08:43:23 +08:00
|
|
|
def pytest_warning_recorded(cls, warning_message, when, nodeid, location):
|
2019-11-23 02:18:07 +08:00
|
|
|
cls.captured.append((warning_message, location))
|
|
|
|
|
2020-12-06 17:20:33 +08:00
|
|
|
pytester.plugins = [CapturedWarnings()]
|
2019-11-23 02:18:07 +08:00
|
|
|
|
|
|
|
return CapturedWarnings
|
|
|
|
|
2020-12-06 17:20:33 +08:00
|
|
|
def test_issue4445_rewrite(self, pytester: Pytester, capwarn) -> None:
|
2019-11-23 02:18:07 +08:00
|
|
|
"""#4445: Make sure the warning points to a reasonable location
|
|
|
|
See origin of _issue_warning_captured at: _pytest.assertion.rewrite.py:241
|
|
|
|
"""
|
2020-12-06 17:20:33 +08:00
|
|
|
pytester.makepyfile(some_mod="")
|
|
|
|
conftest = pytester.makeconftest(
|
2019-11-23 02:18:07 +08:00
|
|
|
"""
|
|
|
|
import some_mod
|
|
|
|
import pytest
|
|
|
|
|
|
|
|
pytest.register_assert_rewrite("some_mod")
|
|
|
|
"""
|
|
|
|
)
|
2020-12-06 17:20:33 +08:00
|
|
|
pytester.parseconfig()
|
2019-11-23 02:18:07 +08:00
|
|
|
|
|
|
|
# with stacklevel=5 the warning originates from register_assert_rewrite
|
|
|
|
# function in the created conftest.py
|
|
|
|
assert len(capwarn.captured) == 1
|
|
|
|
warning, location = capwarn.captured.pop()
|
|
|
|
file, lineno, func = location
|
|
|
|
|
|
|
|
assert "Module already imported" in str(warning.message)
|
|
|
|
assert file == str(conftest)
|
|
|
|
assert func == "<module>" # the above conftest.py
|
|
|
|
assert lineno == 4
|
|
|
|
|
2020-12-06 17:20:33 +08:00
|
|
|
def test_issue4445_preparse(self, pytester: Pytester, capwarn) -> None:
|
2019-11-23 02:18:07 +08:00
|
|
|
"""#4445: Make sure the warning points to a reasonable location
|
|
|
|
See origin of _issue_warning_captured at: _pytest.config.__init__.py:910
|
|
|
|
"""
|
2020-12-06 17:20:33 +08:00
|
|
|
pytester.makeconftest(
|
2019-11-23 02:18:07 +08:00
|
|
|
"""
|
|
|
|
import nothing
|
|
|
|
"""
|
|
|
|
)
|
2020-12-06 17:20:33 +08:00
|
|
|
pytester.parseconfig("--help")
|
2019-11-23 02:18:07 +08:00
|
|
|
|
|
|
|
# with stacklevel=2 the warning should originate from config._preparse and is
|
2021-12-27 20:23:15 +08:00
|
|
|
# thrown by an erroneous conftest.py
|
2019-11-23 02:18:07 +08:00
|
|
|
assert len(capwarn.captured) == 1
|
|
|
|
warning, location = capwarn.captured.pop()
|
|
|
|
file, _, func = location
|
|
|
|
|
|
|
|
assert "could not load initial conftests" in str(warning.message)
|
2020-10-03 04:16:22 +08:00
|
|
|
assert f"config{os.sep}__init__.py" in file
|
2019-11-23 02:18:07 +08:00
|
|
|
assert func == "_preparse"
|
|
|
|
|
2020-09-04 22:57:15 +08:00
|
|
|
@pytest.mark.filterwarnings("default")
|
2020-12-06 17:20:33 +08:00
|
|
|
def test_conftest_warning_captured(self, pytester: Pytester) -> None:
|
2020-09-04 22:57:15 +08:00
|
|
|
"""Warnings raised during importing of conftest.py files is captured (#2891)."""
|
2020-12-06 17:20:33 +08:00
|
|
|
pytester.makeconftest(
|
2020-09-04 22:57:15 +08:00
|
|
|
"""
|
|
|
|
import warnings
|
|
|
|
warnings.warn(UserWarning("my custom warning"))
|
|
|
|
"""
|
|
|
|
)
|
2020-12-06 17:20:33 +08:00
|
|
|
result = pytester.runpytest()
|
2020-09-04 22:57:15 +08:00
|
|
|
result.stdout.fnmatch_lines(
|
|
|
|
["conftest.py:2", "*UserWarning: my custom warning*"]
|
|
|
|
)
|
|
|
|
|
2020-12-06 17:20:33 +08:00
|
|
|
def test_issue4445_import_plugin(self, pytester: Pytester, capwarn) -> None:
|
2020-09-04 22:57:15 +08:00
|
|
|
"""#4445: Make sure the warning points to a reasonable location"""
|
2020-12-06 17:20:33 +08:00
|
|
|
pytester.makepyfile(
|
2019-11-23 02:18:07 +08:00
|
|
|
some_plugin="""
|
|
|
|
import pytest
|
|
|
|
pytest.skip("thing", allow_module_level=True)
|
|
|
|
"""
|
|
|
|
)
|
2020-12-06 17:20:33 +08:00
|
|
|
pytester.syspathinsert()
|
|
|
|
pytester.parseconfig("-p", "some_plugin")
|
2019-11-23 02:18:07 +08:00
|
|
|
|
|
|
|
# with stacklevel=2 the warning should originate from
|
|
|
|
# config.PytestPluginManager.import_plugin is thrown by a skipped plugin
|
|
|
|
|
2020-02-03 21:10:54 +08:00
|
|
|
assert len(capwarn.captured) == 1
|
2019-11-23 02:18:07 +08:00
|
|
|
warning, location = capwarn.captured.pop()
|
|
|
|
file, _, func = location
|
|
|
|
|
|
|
|
assert "skipped plugin 'some_plugin': thing" in str(warning.message)
|
2020-10-03 04:16:22 +08:00
|
|
|
assert f"config{os.sep}__init__.py" in file
|
2020-09-04 22:57:15 +08:00
|
|
|
assert func == "_warn_about_skipped_plugins"
|
2019-11-23 02:18:07 +08:00
|
|
|
|
2020-12-06 17:20:33 +08:00
|
|
|
def test_issue4445_issue5928_mark_generator(self, pytester: Pytester) -> None:
|
2019-11-23 02:18:07 +08:00
|
|
|
"""#4445 and #5928: Make sure the warning from an unknown mark points to
|
|
|
|
the test file where this mark is used.
|
|
|
|
"""
|
2020-12-06 17:20:33 +08:00
|
|
|
testfile = pytester.makepyfile(
|
2019-11-23 02:18:07 +08:00
|
|
|
"""
|
|
|
|
import pytest
|
|
|
|
|
|
|
|
@pytest.mark.unknown
|
|
|
|
def test_it():
|
|
|
|
pass
|
|
|
|
"""
|
|
|
|
)
|
2020-12-06 17:20:33 +08:00
|
|
|
result = pytester.runpytest_subprocess()
|
2019-11-23 02:18:07 +08:00
|
|
|
# with stacklevel=2 the warning should originate from the above created test file
|
|
|
|
result.stdout.fnmatch_lines_random(
|
|
|
|
[
|
2021-04-14 17:49:09 +08:00
|
|
|
f"*{testfile}:3*",
|
2019-11-23 02:18:07 +08:00
|
|
|
"*Unknown pytest.mark.unknown*",
|
|
|
|
]
|
|
|
|
)
|
2022-02-15 21:00:50 +08:00
|
|
|
|
|
|
|
|
2023-05-30 18:06:13 +08:00
|
|
|
def test_warning_on_testpaths_not_found(pytester: Pytester) -> None:
|
|
|
|
# Check for warning when testpaths set, but not found by glob
|
|
|
|
pytester.makeini(
|
|
|
|
"""
|
|
|
|
[pytest]
|
|
|
|
testpaths = absent
|
|
|
|
"""
|
|
|
|
)
|
|
|
|
result = pytester.runpytest()
|
|
|
|
result.stdout.fnmatch_lines(
|
|
|
|
["*ConfigWarning: No files were found in testpaths*", "*1 warning*"]
|
|
|
|
)
|
|
|
|
|
|
|
|
|
2022-02-15 21:00:50 +08:00
|
|
|
def test_resource_warning(pytester: Pytester, monkeypatch: pytest.MonkeyPatch) -> None:
|
|
|
|
# Some platforms (notably PyPy) don't have tracemalloc.
|
|
|
|
# We choose to explicitly not skip this in case tracemalloc is not
|
|
|
|
# available, using `importorskip("tracemalloc")` for example,
|
|
|
|
# because we want to ensure the same code path does not break in those platforms.
|
|
|
|
try:
|
2024-02-09 17:14:36 +08:00
|
|
|
import tracemalloc # noqa: F401
|
2022-02-15 21:00:50 +08:00
|
|
|
|
|
|
|
has_tracemalloc = True
|
|
|
|
except ImportError:
|
|
|
|
has_tracemalloc = False
|
|
|
|
|
|
|
|
# Explicitly disable PYTHONTRACEMALLOC in case pytest's test suite is running
|
|
|
|
# with it enabled.
|
|
|
|
monkeypatch.delenv("PYTHONTRACEMALLOC", raising=False)
|
|
|
|
|
|
|
|
pytester.makepyfile(
|
|
|
|
"""
|
|
|
|
def open_file(p):
|
2023-06-20 19:55:40 +08:00
|
|
|
f = p.open("r", encoding="utf-8")
|
2022-02-15 21:00:50 +08:00
|
|
|
assert p.read_text() == "hello"
|
|
|
|
|
|
|
|
def test_resource_warning(tmp_path):
|
|
|
|
p = tmp_path.joinpath("foo.txt")
|
2023-06-20 19:55:40 +08:00
|
|
|
p.write_text("hello", encoding="utf-8")
|
2022-02-15 21:00:50 +08:00
|
|
|
open_file(p)
|
|
|
|
"""
|
|
|
|
)
|
|
|
|
result = pytester.run(sys.executable, "-Xdev", "-m", "pytest")
|
|
|
|
expected_extra = (
|
|
|
|
[
|
|
|
|
"*ResourceWarning* unclosed file*",
|
|
|
|
"*Enable tracemalloc to get traceback where the object was allocated*",
|
|
|
|
"*See https* for more info.",
|
|
|
|
]
|
|
|
|
if has_tracemalloc
|
|
|
|
else []
|
|
|
|
)
|
|
|
|
result.stdout.fnmatch_lines([*expected_extra, "*1 passed*"])
|
|
|
|
|
|
|
|
monkeypatch.setenv("PYTHONTRACEMALLOC", "20")
|
|
|
|
|
|
|
|
result = pytester.run(sys.executable, "-Xdev", "-m", "pytest")
|
|
|
|
expected_extra = (
|
|
|
|
[
|
|
|
|
"*ResourceWarning* unclosed file*",
|
|
|
|
"*Object allocated at*",
|
|
|
|
]
|
|
|
|
if has_tracemalloc
|
|
|
|
else []
|
|
|
|
)
|
|
|
|
result.stdout.fnmatch_lines([*expected_extra, "*1 passed*"])
|