I am using pytest and I wish to log some log output that will be captured and displayed should a test fail.
To do this, I wish to add a new log level to the default pytest logger. My rationale for this is that my application outputs to the INFO level anyway, so I wish to avoid capturing those logs during the test. For that reason, I cannot simply change the log level to INFO.
Using the answers to this question I have derived the following solution, but it is not working. The error I see appears to be noted in a comment on accepted answer to the question, but there is no response.
AttributeError: module ‘logging’ has no attribute ‘test_info’
How can I correctly add a custom logging level?
Using pytest fixture and tests
import logging
import pytest
@pytest.fixture(scope='session', autouse=True)
def logging_format(level_name: str='TEST_INFO', level_number: int=31):
def log_test_info(self, message, *args, **kwargs):
if self.isEnabledFor(level_number):
self._log(level_number, message, args, **kwargs)
logging.addLevelName(level_number, level_name)
setattr(logging, level_name, level_number)
setattr(logging.getLoggerClass(), level_name.lower(), log_test_info)
def test():
logging.test_info('Some log data.')
assert True
Not using pytest fixture and tests
To be sure this is not a pytest issue, I it’s also possible to replicate the issue without using it.
import logging
level_name = 'TEST_INFO'
level_number = 31
def log_test_info(self, message, *args, **kwargs):
if self.isEnabledFor(level_number):
self._log(level_number, message, args, **kwargs)
logging.addLevelName(level_number, level_name)
setattr(logging, level_name, level_number)
setattr(logging.getLoggerClass(), level_name.lower(), log_test_info)
logging.test_info('Some log data.')
assert True
>Solution :
In this code there is a misunderstanding between a logger instance and the logger module.
To be able to call the test_log method in the original code you need to obtain a logger instance eg:
# After the existing code
logger = logging.getLogger()
logger.test_info("Some log data.")
As you have added the test_info method to the loggerClass it will be available to the logger instance.
To have the method available on the logging module the function needs to be created for that purpose and added to the module:
# After the existing code
def module_test_info(message, *args, **kwargs):
logging.log(level_number, message, *args, **kwargs)
setattr(logging, level_name.lower(), module_test_info)
This will add the module_test_info function to the logging module with the name test_info you will be able to call it as such logging.test_level("Some log data.")