Ensure logging tests always cleanup after themselves

Logging has many global states, and we did foresee this by creating a ``cleanup_disabled_logging`` fixture,
however one might still forget to use it and failures leak later -- sometimes not even in the same PR, because the order
of the tests might change in the future, specially when running under xdist.

This problem surfaced during pytest-dev/pytest#11530, where tests unrelated to the change started to fail.
This commit is contained in:
Bruno Oliveira 2023-10-21 15:35:07 -03:00
parent ee53433542
commit 395bbae8a2
1 changed files with 7 additions and 10 deletions

View File

@ -1,5 +1,6 @@
# mypy: disable-error-code="attr-defined" # mypy: disable-error-code="attr-defined"
import logging import logging
from typing import Iterator
import pytest import pytest
from _pytest.logging import caplog_records_key from _pytest.logging import caplog_records_key
@ -9,8 +10,8 @@ logger = logging.getLogger(__name__)
sublogger = logging.getLogger(__name__ + ".baz") sublogger = logging.getLogger(__name__ + ".baz")
@pytest.fixture @pytest.fixture(autouse=True)
def cleanup_disabled_logging(): def cleanup_disabled_logging() -> Iterator[None]:
"""Simple fixture that ensures that a test doesn't disable logging. """Simple fixture that ensures that a test doesn't disable logging.
This is necessary because ``logging.disable()`` is global, so a test disabling logging This is necessary because ``logging.disable()`` is global, so a test disabling logging
@ -42,7 +43,7 @@ def test_change_level(caplog):
assert "CRITICAL" in caplog.text assert "CRITICAL" in caplog.text
def test_change_level_logging_disabled(caplog, cleanup_disabled_logging): def test_change_level_logging_disabled(caplog):
logging.disable(logging.CRITICAL) logging.disable(logging.CRITICAL)
assert logging.root.manager.disable == logging.CRITICAL assert logging.root.manager.disable == logging.CRITICAL
caplog.set_level(logging.WARNING) caplog.set_level(logging.WARNING)
@ -85,9 +86,7 @@ def test_change_level_undo(pytester: Pytester) -> None:
result.stdout.no_fnmatch_line("*log from test2*") result.stdout.no_fnmatch_line("*log from test2*")
def test_change_disabled_level_undo( def test_change_disabled_level_undo(pytester: Pytester) -> None:
pytester: Pytester, cleanup_disabled_logging
) -> None:
"""Ensure that '_force_enable_logging' in 'set_level' is undone after the end of the test. """Ensure that '_force_enable_logging' in 'set_level' is undone after the end of the test.
Tests the logging output themselves (affected by disabled logging level). Tests the logging output themselves (affected by disabled logging level).
@ -159,7 +158,7 @@ def test_with_statement(caplog):
assert "CRITICAL" in caplog.text assert "CRITICAL" in caplog.text
def test_with_statement_logging_disabled(caplog, cleanup_disabled_logging): def test_with_statement_logging_disabled(caplog):
logging.disable(logging.CRITICAL) logging.disable(logging.CRITICAL)
assert logging.root.manager.disable == logging.CRITICAL assert logging.root.manager.disable == logging.CRITICAL
with caplog.at_level(logging.WARNING): with caplog.at_level(logging.WARNING):
@ -197,9 +196,7 @@ def test_with_statement_logging_disabled(caplog, cleanup_disabled_logging):
("NOTVALIDLEVEL", logging.NOTSET), ("NOTVALIDLEVEL", logging.NOTSET),
], ],
) )
def test_force_enable_logging_level_string( def test_force_enable_logging_level_string(caplog, level_str, expected_disable_level):
caplog, cleanup_disabled_logging, level_str, expected_disable_level
):
"""Test _force_enable_logging using a level string. """Test _force_enable_logging using a level string.
``expected_disable_level`` is one level below ``level_str`` because the disabled log level ``expected_disable_level`` is one level below ``level_str`` because the disabled log level