I have a suite of unit tests for a python module and use Pytest to run those tests. I am now starting to use the standard logging library in my library and would need help solving two issues:
- How to prevent logs into files when running the test suite, to prevent files growing and to prevent unhelpful entries in real log files.
- How to capture the logs inside unit tests, to be able to run assertions on the logs that the library generates.
The module that I am trying to test configures the logging library in __init__.py
to log into a file and logs entries in the module code using the info method. That works fine and when I run the code the right log entries appear in the file ok. -- see code below --
I have tried to use the caplog
fixture in pytest -- see code and output below -- but the effect I get is:
- log entries are included into the file (logs generated in the runs from the test using caplog and all other tests)
caplog.text
is empty
Unit Tests Code
import library.module
class TestFunction:
def test_something_else(self):
library.module.function():
assert True
def test_logs(self,caplog)
library.module.function():
assert "desired" in caplog.text
Test Output
(...)
> assert "desired" in caplog.text
E AssertionError: assert 'desired' in ''
E where '' = <_pytest.logging.LogCaptureFixture object at (...).text
(...)
Log entries after running test suite
2021-12-07 11:10:05,915 - library.module - INFO - desired
2021-12-07 11:10:05,917 - library.module - INFO - desired
Logging module configuration
__init__.py
import logging.config
import yaml
with open("logging.yaml") as f:
conf_dict = yaml.safe_load(f)
logging.config.dictConfig(conf_dict)
logging.yaml
version: 1
formatters:
simple:
format: '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
handlers:
training:
class: logging.FileHandler
level: DEBUG
formatter: simple
filename: logs/test_log
loggers:
library.module:
level: DEBUG
handlers: [training]
propagate: no
root:
level: DEBUG
handlers: []
Module under test
import logging
logger = logging.getLogger(__name__)
def function():
logger.info("desired")
File Structure
.
├── library
│ ├── module.py
│ └── __init__.py
├── tests
│ └── test_module.py
└── logs
└── test_log
CodePudding user response:
To avoid writing to the log file, I suggest that, in test_module.py
, you simply mock the logger and use it in your test, like this:
import pytest
import library.module
@pytest.fixture
def logger(mocker):
return mocker.patch("library.module.logger.info")
class TestFunction:
def test_something_else(self):
library.module.function():
assert True
def test_logs(self,logger)
library.module.function():
logger.assert_called_with("desired")