Skip to content

Commit

Permalink
[7.4.x] Ensure logging tests always cleanup after themselves (#11541)
Browse files Browse the repository at this point in the history
Co-authored-by: Bruno Oliveira <nicoddemus@gmail.com>
  • Loading branch information
github-actions[bot] and nicoddemus authored Oct 23, 2023
1 parent a517827 commit 5dc7725
Showing 1 changed file with 33 additions and 23 deletions.
56 changes: 33 additions & 23 deletions testing/logging/test_fixture.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# mypy: disable-error-code="attr-defined"
# mypy: disallow-untyped-defs
import logging
from typing import Iterator

import pytest
from _pytest.logging import caplog_records_key
Expand All @@ -9,8 +11,8 @@
sublogger = logging.getLogger(__name__ + ".baz")


@pytest.fixture
def cleanup_disabled_logging():
@pytest.fixture(autouse=True)
def cleanup_disabled_logging() -> Iterator[None]:
"""Simple fixture that ensures that a test doesn't disable logging.
This is necessary because ``logging.disable()`` is global, so a test disabling logging
Expand All @@ -27,7 +29,7 @@ def test_fixture_help(pytester: Pytester) -> None:
result.stdout.fnmatch_lines(["*caplog*"])


def test_change_level(caplog):
def test_change_level(caplog: pytest.LogCaptureFixture) -> None:
caplog.set_level(logging.INFO)
logger.debug("handler DEBUG level")
logger.info("handler INFO level")
Expand All @@ -42,7 +44,7 @@ def test_change_level(caplog):
assert "CRITICAL" in caplog.text


def test_change_level_logging_disabled(caplog, cleanup_disabled_logging):
def test_change_level_logging_disabled(caplog: pytest.LogCaptureFixture) -> None:
logging.disable(logging.CRITICAL)
assert logging.root.manager.disable == logging.CRITICAL
caplog.set_level(logging.WARNING)
Expand Down Expand Up @@ -85,9 +87,7 @@ def test2(caplog):
result.stdout.no_fnmatch_line("*log from test2*")


def test_change_disabled_level_undo(
pytester: Pytester, cleanup_disabled_logging
) -> None:
def test_change_disabled_level_undo(pytester: Pytester) -> None:
"""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).
Expand Down Expand Up @@ -144,7 +144,7 @@ def test3(caplog):
result.assert_outcomes(passed=3)


def test_with_statement(caplog):
def test_with_statement(caplog: pytest.LogCaptureFixture) -> None:
with caplog.at_level(logging.INFO):
logger.debug("handler DEBUG level")
logger.info("handler INFO level")
Expand All @@ -159,7 +159,7 @@ def test_with_statement(caplog):
assert "CRITICAL" in caplog.text


def test_with_statement_logging_disabled(caplog, cleanup_disabled_logging):
def test_with_statement_logging_disabled(caplog: pytest.LogCaptureFixture) -> None:
logging.disable(logging.CRITICAL)
assert logging.root.manager.disable == logging.CRITICAL
with caplog.at_level(logging.WARNING):
Expand Down Expand Up @@ -198,8 +198,8 @@ def test_with_statement_logging_disabled(caplog, cleanup_disabled_logging):
],
)
def test_force_enable_logging_level_string(
caplog, cleanup_disabled_logging, level_str, expected_disable_level
):
caplog: pytest.LogCaptureFixture, level_str: str, expected_disable_level: int
) -> None:
"""Test _force_enable_logging using a level string.
``expected_disable_level`` is one level below ``level_str`` because the disabled log level
Expand All @@ -218,15 +218,15 @@ def test_force_enable_logging_level_string(
assert test_logger.manager.disable == expected_disable_level


def test_log_access(caplog):
def test_log_access(caplog: pytest.LogCaptureFixture) -> None:
caplog.set_level(logging.INFO)
logger.info("boo %s", "arg")
assert caplog.records[0].levelname == "INFO"
assert caplog.records[0].msg == "boo %s"
assert "boo arg" in caplog.text


def test_messages(caplog):
def test_messages(caplog: pytest.LogCaptureFixture) -> None:
caplog.set_level(logging.INFO)
logger.info("boo %s", "arg")
logger.info("bar %s\nbaz %s", "arg1", "arg2")
Expand All @@ -247,22 +247,22 @@ def test_messages(caplog):
assert "Exception" not in caplog.messages[-1]


def test_record_tuples(caplog):
def test_record_tuples(caplog: pytest.LogCaptureFixture) -> None:
caplog.set_level(logging.INFO)
logger.info("boo %s", "arg")

assert caplog.record_tuples == [(__name__, logging.INFO, "boo arg")]


def test_unicode(caplog):
def test_unicode(caplog: pytest.LogCaptureFixture) -> None:
caplog.set_level(logging.INFO)
logger.info("bū")
assert caplog.records[0].levelname == "INFO"
assert caplog.records[0].msg == "bū"
assert "bū" in caplog.text


def test_clear(caplog):
def test_clear(caplog: pytest.LogCaptureFixture) -> None:
caplog.set_level(logging.INFO)
logger.info("bū")
assert len(caplog.records)
Expand All @@ -273,15 +273,19 @@ def test_clear(caplog):


@pytest.fixture
def logging_during_setup_and_teardown(caplog):
def logging_during_setup_and_teardown(
caplog: pytest.LogCaptureFixture,
) -> Iterator[None]:
caplog.set_level("INFO")
logger.info("a_setup_log")
yield
logger.info("a_teardown_log")
assert [x.message for x in caplog.get_records("teardown")] == ["a_teardown_log"]


def test_caplog_captures_for_all_stages(caplog, logging_during_setup_and_teardown):
def test_caplog_captures_for_all_stages(
caplog: pytest.LogCaptureFixture, logging_during_setup_and_teardown: None
) -> None:
assert not caplog.records
assert not caplog.get_records("call")
logger.info("a_call_log")
Expand All @@ -290,25 +294,31 @@ def test_caplog_captures_for_all_stages(caplog, logging_during_setup_and_teardow
assert [x.message for x in caplog.get_records("setup")] == ["a_setup_log"]

# This reaches into private API, don't use this type of thing in real tests!
assert set(caplog._item.stash[caplog_records_key]) == {"setup", "call"}
caplog_records = caplog._item.stash[caplog_records_key]
assert set(caplog_records) == {"setup", "call"}


def test_clear_for_call_stage(caplog, logging_during_setup_and_teardown):
def test_clear_for_call_stage(
caplog: pytest.LogCaptureFixture, logging_during_setup_and_teardown: None
) -> None:
logger.info("a_call_log")
assert [x.message for x in caplog.get_records("call")] == ["a_call_log"]
assert [x.message for x in caplog.get_records("setup")] == ["a_setup_log"]
assert set(caplog._item.stash[caplog_records_key]) == {"setup", "call"}
caplog_records = caplog._item.stash[caplog_records_key]
assert set(caplog_records) == {"setup", "call"}

caplog.clear()

assert caplog.get_records("call") == []
assert [x.message for x in caplog.get_records("setup")] == ["a_setup_log"]
assert set(caplog._item.stash[caplog_records_key]) == {"setup", "call"}
caplog_records = caplog._item.stash[caplog_records_key]
assert set(caplog_records) == {"setup", "call"}

logging.info("a_call_log_after_clear")
assert [x.message for x in caplog.get_records("call")] == ["a_call_log_after_clear"]
assert [x.message for x in caplog.get_records("setup")] == ["a_setup_log"]
assert set(caplog._item.stash[caplog_records_key]) == {"setup", "call"}
caplog_records = caplog._item.stash[caplog_records_key]
assert set(caplog_records) == {"setup", "call"}


def test_ini_controls_global_log_level(pytester: Pytester) -> None:
Expand Down

0 comments on commit 5dc7725

Please sign in to comment.