See my minimal example below for reproducing the issue:
import logging
import logging.config
def test_logging(caplog):
LOGGING_CONFIG = {
"version": 1,
"disable_existing_loggers": False,
"formatters": {
"default": {
"format": "%(asctime)s - %(name)s - %(levelname)s - %(message)s",
},
},
"handlers": {
"console": {
"class": "logging.StreamHandler",
"formatter": "default",
"level": "DEBUG",
},
},
"loggers": {
"": { # root logger
"handlers": ["console"],
"level": "DEBUG",
"propagate": True,
},
},
}
logging.config.dictConfig(LOGGING_CONFIG)
logger = logging.getLogger("root_module.sub1.sub2")
logger.setLevel(logging.DEBUG)
assert logger.propagate is True
assert logger.getEffectiveLevel() == logging.DEBUG
with caplog.at_level(logging.DEBUG):
logger.debug("š„ DEBUG msg")
logger.info("š INFO msg")
logger.warning("ā ļø WARNING msg")
logger.error("ā ERROR msg")
logger.critical("š CRITICAL msg")
print("š„ caplog.messages:", caplog.messages)
# Final assertion
assert any("CRITICAL" in r or "š" in r for r in caplog.messages)
Running pytest -s
outputs:
tests/test_logs.py 2025-04-16 17:06:03,983 - root_module.sub1.sub2 - DEBUG - š„ DEBUG msg
2025-04-16 17:06:03,983 - root_module.sub1.sub2 - INFO - š INFO msg
2025-04-16 17:06:03,983 - root_module.sub1.sub2 - WARNING - ā ļø WARNING msg
2025-04-16 17:06:03,983 - root_module.sub1.sub2 - ERROR - ā ERROR msg
2025-04-16 17:06:03,983 - root_module.sub1.sub2 - CRITICAL - š CRITICAL msg
š„ caplog.messages: []
Pytest version is 8.3.5
. I don't think it matters, but my setup.cfg
:
[tool:pytest]
testpaths =
tests
I am expecting caplog.records
to contain all 5 logs, but it is empty list.
You're not supposed to configure logging during a test. Further, if any real code under test tries to configure loggers, you should probably patch that out. The way caplog
fixture works is by adding a capturing handler, so if you've already configured the logging framework, or attempt to reconfigure it during test, then you're interfering with pytest's functionality.
This is even explicitly mentioned in the caplog
documentation:
ā ļø Warning
The
caplog
fixture adds a handler to the root logger to capture logs. If the root logger is modified during a test, for example withlogging.config.dictConfig
, this handler may be removed and cause no logs to be captured. To avoid this, ensure that any root logger configuration only adds to the existing handlers.
Remove the runtime logging configuration makes the test pass:
import logging
def test_logging(caplog):
logger = logging.getLogger("root_module.sub1.sub2")
with caplog.at_level(logging.DEBUG):
logger.debug("š„ DEBUG msg")
logger.info("š INFO msg")
logger.warning("ā ļø WARNING msg")
logger.error("ā ERROR msg")
logger.critical("š CRITICAL msg")
print("š„ caplog.messages:", caplog.messages)
# Final assertion
assert any("CRITICAL" in r or "š" in r for r in caplog.messages)