diff --git a/changelog/4487.bugfix.rst b/changelog/4487.bugfix.rst deleted file mode 100644 index 3ba8d4731..000000000 --- a/changelog/4487.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -During teardown of the python process, and on rare occasions, capture attributes can be ``None`` while trying to resume global capture. diff --git a/changelog/4500.bugfix.rst b/changelog/4500.bugfix.rst new file mode 100644 index 000000000..b84b6b117 --- /dev/null +++ b/changelog/4500.bugfix.rst @@ -0,0 +1 @@ +When a fixture yields and a log call is made after the test runs, and, if the test is interrupted, capture attributes are ``None``. diff --git a/testing/test_capture.py b/testing/test_capture.py index 47aba70d4..d44b58ee0 100644 --- a/testing/test_capture.py +++ b/testing/test_capture.py @@ -302,14 +302,14 @@ class TestLoggingInteraction(object): """\ import logging def setup_function(function): - logging.warn("hello1") + logging.warning("hello1") def test_logging(): - logging.warn("hello2") + logging.warning("hello2") assert 0 def teardown_function(function): - logging.warn("hello3") + logging.warning("hello3") assert 0 """ ) @@ -328,14 +328,14 @@ class TestLoggingInteraction(object): """\ import logging def setup_module(function): - logging.warn("hello1") + logging.warning("hello1") def test_logging(): - logging.warn("hello2") + logging.warning("hello2") assert 0 def teardown_module(function): - logging.warn("hello3") + logging.warning("hello3") assert 0 """ ) @@ -354,7 +354,7 @@ class TestLoggingInteraction(object): """\ import logging logging.basicConfig() - logging.warn("hello435") + logging.warning("hello435") """ ) # make sure that logging is still captured in tests @@ -375,7 +375,7 @@ class TestLoggingInteraction(object): """\ def test_hello(): import logging - logging.warn("hello433") + logging.warning("hello433") assert 0 """ ) @@ -385,6 +385,40 @@ class TestLoggingInteraction(object): assert "something" not in result.stderr.str() assert "operation on closed file" not in result.stderr.str() + def test_logging_after_cap_stopped(self, testdir): + testdir.makeconftest( + """\ + import pytest + import logging + + log = logging.getLogger(__name__) + + @pytest.fixture + def log_on_teardown(): + yield + log.warning('Logging on teardown') + """ + ) + # make sure that logging is still captured in tests + p = testdir.makepyfile( + """\ + def test_hello(log_on_teardown): + import logging + logging.warning("hello433") + assert 1 + raise KeyboardInterrupt() + """ + ) + result = testdir.runpytest_subprocess(p, "--log-cli-level", "info") + assert result.ret != 0 + result.stdout.fnmatch_lines( + ["*WARNING*hello433*", "*WARNING*Logging on teardown*"] + ) + assert ( + "AttributeError: 'NoneType' object has no attribute 'resume_capturing'" + not in result.stderr.str() + ) + class TestCaptureFixture(object): @pytest.mark.parametrize("opt", [[], ["-s"]]) @@ -1300,13 +1334,13 @@ def test_capturing_and_logging_fundamentals(testdir, method): Capture=capture.%s) cap.start_capturing() - logging.warn("hello1") + logging.warning("hello1") outerr = cap.readouterr() print("suspend, captured %%s" %%(outerr,)) - logging.warn("hello2") + logging.warning("hello2") cap.pop_outerr_to_orig() - logging.warn("hello3") + logging.warning("hello3") outerr = cap.readouterr() print("suspend2, captured %%s" %% (outerr,))