| # -*- coding: utf8 -*- |
| from __future__ import unicode_literals |
| |
| import sys |
| |
| import pytest |
| |
| |
| WARNINGS_SUMMARY_HEADER = "warnings summary" |
| |
| |
| @pytest.fixture |
| def pyfile_with_warnings(testdir, request): |
| """ |
| Create a test file which calls a function in a module which generates warnings. |
| """ |
| testdir.syspathinsert() |
| test_name = request.function.__name__ |
| module_name = test_name.lstrip("test_") + "_module" |
| testdir.makepyfile( |
| **{ |
| module_name: """ |
| import warnings |
| def foo(): |
| warnings.warn(UserWarning("user warning")) |
| warnings.warn(RuntimeWarning("runtime warning")) |
| return 1 |
| """, |
| test_name: """ |
| import {module_name} |
| def test_func(): |
| assert {module_name}.foo() == 1 |
| """.format( |
| module_name=module_name |
| ), |
| } |
| ) |
| |
| |
| @pytest.mark.filterwarnings("always") |
| def test_normal_flow(testdir, pyfile_with_warnings): |
| """ |
| Check that the warnings section is displayed, containing test node ids followed by |
| all warnings generated by that test node. |
| """ |
| result = testdir.runpytest() |
| result.stdout.fnmatch_lines( |
| [ |
| "*== %s ==*" % WARNINGS_SUMMARY_HEADER, |
| "*test_normal_flow.py::test_func", |
| "*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*", |
| ] |
| ) |
| assert result.stdout.str().count("test_normal_flow.py::test_func") == 1 |
| |
| |
| @pytest.mark.filterwarnings("always") |
| def test_setup_teardown_warnings(testdir, pyfile_with_warnings): |
| testdir.makepyfile( |
| """ |
| 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 |
| """ |
| ) |
| result = testdir.runpytest() |
| result.stdout.fnmatch_lines( |
| [ |
| "*== %s ==*" % WARNINGS_SUMMARY_HEADER, |
| "*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"]) |
| def test_as_errors(testdir, pyfile_with_warnings, method): |
| args = ("-W", "error") if method == "cmdline" else () |
| if method == "ini": |
| testdir.makeini( |
| """ |
| [pytest] |
| filterwarnings= error |
| """ |
| ) |
| result = testdir.runpytest(*args) |
| result.stdout.fnmatch_lines( |
| [ |
| "E UserWarning: user warning", |
| "as_errors_module.py:3: UserWarning", |
| "* 1 failed in *", |
| ] |
| ) |
| |
| |
| @pytest.mark.parametrize("method", ["cmdline", "ini"]) |
| def test_ignore(testdir, pyfile_with_warnings, method): |
| args = ("-W", "ignore") if method == "cmdline" else () |
| if method == "ini": |
| testdir.makeini( |
| """ |
| [pytest] |
| filterwarnings= ignore |
| """ |
| ) |
| |
| result = testdir.runpytest(*args) |
| result.stdout.fnmatch_lines(["* 1 passed in *"]) |
| assert WARNINGS_SUMMARY_HEADER not in result.stdout.str() |
| |
| |
| @pytest.mark.skipif( |
| sys.version_info < (3, 0), reason="warnings message is unicode is ok in python3" |
| ) |
| @pytest.mark.filterwarnings("always") |
| def test_unicode(testdir, pyfile_with_warnings): |
| testdir.makepyfile( |
| """ |
| # -*- coding: utf8 -*- |
| import warnings |
| import pytest |
| |
| |
| @pytest.fixture |
| def fix(): |
| warnings.warn(u"测试") |
| yield |
| |
| def test_func(fix): |
| pass |
| """ |
| ) |
| result = testdir.runpytest() |
| result.stdout.fnmatch_lines( |
| [ |
| "*== %s ==*" % WARNINGS_SUMMARY_HEADER, |
| "*test_unicode.py:8: UserWarning: \u6d4b\u8bd5*", |
| "* 1 passed, 1 warnings*", |
| ] |
| ) |
| |
| |
| @pytest.mark.skipif( |
| sys.version_info >= (3, 0), |
| reason="warnings message is broken as it is not str instance", |
| ) |
| def test_py2_unicode(testdir, pyfile_with_warnings): |
| if ( |
| getattr(sys, "pypy_version_info", ())[:2] == (5, 9) |
| and sys.platform.startswith("win") |
| ): |
| pytest.xfail("fails with unicode error on PyPy2 5.9 and Windows (#2905)") |
| testdir.makepyfile( |
| """ |
| # -*- coding: utf8 -*- |
| import warnings |
| import pytest |
| |
| |
| @pytest.fixture |
| def fix(): |
| warnings.warn(u"测试") |
| yield |
| |
| @pytest.mark.filterwarnings('always') |
| def test_func(fix): |
| pass |
| """ |
| ) |
| result = testdir.runpytest() |
| result.stdout.fnmatch_lines( |
| [ |
| "*== %s ==*" % WARNINGS_SUMMARY_HEADER, |
| "*test_py2_unicode.py:8: UserWarning: \\u6d4b\\u8bd5", |
| '*warnings.warn(u"\u6d4b\u8bd5")', |
| "*warnings.py:*: UnicodeWarning: Warning is using unicode non*", |
| "* 1 passed, 2 warnings*", |
| ] |
| ) |
| |
| |
| def test_py2_unicode_ascii(testdir): |
| """Ensure that our warning about 'unicode warnings containing non-ascii messages' |
| does not trigger with ascii-convertible messages""" |
| testdir.makeini("[pytest]") |
| testdir.makepyfile( |
| """ |
| import pytest |
| import warnings |
| |
| @pytest.mark.filterwarnings('always') |
| def test_func(): |
| warnings.warn(u"hello") |
| """ |
| ) |
| result = testdir.runpytest() |
| result.stdout.fnmatch_lines( |
| [ |
| "*== %s ==*" % WARNINGS_SUMMARY_HEADER, |
| '*warnings.warn(u"hello")', |
| "* 1 passed, 1 warnings in*", |
| ] |
| ) |
| |
| |
| def test_works_with_filterwarnings(testdir): |
| """Ensure our warnings capture does not mess with pre-installed filters (#2430).""" |
| testdir.makepyfile( |
| """ |
| import warnings |
| |
| class MyWarning(Warning): |
| pass |
| |
| warnings.filterwarnings("error", category=MyWarning) |
| |
| class TestWarnings(object): |
| def test_my_warning(self): |
| try: |
| warnings.warn(MyWarning("warn!")) |
| assert False |
| except MyWarning: |
| assert True |
| """ |
| ) |
| result = testdir.runpytest() |
| result.stdout.fnmatch_lines(["*== 1 passed in *"]) |
| |
| |
| @pytest.mark.parametrize("default_config", ["ini", "cmdline"]) |
| def test_filterwarnings_mark(testdir, default_config): |
| """ |
| Test ``filterwarnings`` mark works and takes precedence over command line and ini options. |
| """ |
| if default_config == "ini": |
| testdir.makeini( |
| """ |
| [pytest] |
| filterwarnings = always |
| """ |
| ) |
| testdir.makepyfile( |
| """ |
| 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()) |
| """ |
| ) |
| result = testdir.runpytest("-W always" if default_config == "cmdline" else "") |
| result.stdout.fnmatch_lines(["*= 1 failed, 2 passed, 1 warnings in *"]) |
| |
| |
| def test_non_string_warning_argument(testdir): |
| """Non-str argument passed to warning breaks pytest (#2956)""" |
| testdir.makepyfile( |
| """ |
| import warnings |
| import pytest |
| |
| def test(): |
| warnings.warn(UserWarning(1, u'foo')) |
| """ |
| ) |
| result = testdir.runpytest("-W", "always") |
| result.stdout.fnmatch_lines(["*= 1 passed, 1 warnings in *"]) |