Can assertLogs check the format of a log message?

Viewed 1274

Can I use Python's unittest assertLogs to check the formatting of a log message?

def test_log_format(self):
    h.config_common_log(level=logging.DEBUG)
    h.get_log().debug('outside context')
    with self.assertLogs(level=logging.DEBUG) as a_log:
        h.get_log().debug('my_message - incontext')     
        self.assertRegex(a_log.output[0], ':\d+:my_message') # This fails
        # This shows the log data itself is correct, just the output message is wrong
        print('a_log.ouput={}\ta_log={!s}'.format(a_log.output, a_log))

# This was added to learn varying the logger would help. It did not.
def get_log():
    return logging.getLogger()

def config_common_log(level=logging.WARNING):
    get_log().setLevel(level)
    ch = logging.StreamHandler()
    ch.setFormatter(logging.Formatter('%(module)s:%(funcName)s:%(lineno)s:%(message)s'))  # Despite this format statement.
    get_log().addHandler(ch)

What has me puzzled is the 'outside context' log message include the line number, but the 'my message - in context' log message shows the default format.

My current hypothesis is that the assertLogs only checks one StreamHandler and (quite reasonably) it use the default StreamHandler with its default Formatter for a_msg. To test my Formatter and StreamHandlder, I would need another approach.

1 Answers

I had this exact question myself, and I found the comment from nodakai very helpful.

Just to expand on that, I employed the following hack to be able to test my log message formatting:

from mylibrary import MY_LOGGING_FORMAT
from unittest import case
case._AssertLogsContext.LOGGING_FORMAT = MY_LOGGING_FORMAT

The format I defined in MY_LOGGING_FORMAT is what I pass into logging.Formatter(...). This hack forces assertLogs to use the same format.

Related