Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Writing a unit test for Python logger formatted output

How could you write a unittest in Python that would test that the output from a logger is indeed in the format you expect (i.e. set through a call to logging.basicConfig())? I'm thinking along the lines of a custom StreamHandler and use of the 're' library but it doesn't look like LogRecord passed to StreamHandler.emit() can give me the string that will be output.

like image 213
Graeme Avatar asked Jun 22 '12 23:06

Graeme


People also ask

How do you mock a logger in Python?

Just prefix your function with @mock. patch. object(logging. getLogger('path.to.

Should you unit test logger?

I would definitely consider unit tests for logging scenarios. when testing, think about the information you would require in a situation where the code has failed. if you have a live issue you'd want to be reassured that you have enough information to find the cause of the issue.

How do I print logger information in Python?

Use logging Module to Print Log Message to a File in PythongetLogger(name) method. There is a convention to use __name__ variable as the name of the logger. Once we have created a new logger, we should remember to log all our messages using the new logger.info() instead of the root's logging.info() method.


1 Answers

From the documentation (http://packages.python.org/testfixtures/logging.html):

To help with this, TestFixtures allows you to easily capture the output of calls to Python’s logging framework and make sure they were as expected. There are three different techniques, depending on the type of test you are writing.

  1. The context manager
  2. The decorator
  3. The manual usage

The examples are included in the documentation. The shortened version is below.

The context manager

>>> import logging
>>> from testfixtures import LogCapture
>>> with LogCapture() as l:
...     logger = logging.getLogger()
...     logger.info('a message')
...     logger.error('an error')

And after that you can check the logs for equality:

>>> l.check(
...     ('root', 'INFO', 'a message'),
...     ('root', 'ERROR', 'another error'),
...     )
Traceback (most recent call last):
 ...
AssertionError: Sequence not as expected:

same:
(('root', 'INFO', 'a message'),)

first:
(('root', 'ERROR', 'another error'),)

second:
(('root', 'ERROR', 'an error'),)

The decorator

Similar to the previous, but applied to specific function:

from testfixtures import log_capture

@log_capture()
def test_function(l):
    logger = logging.getLogger()
    logger.info('a message')
    logger.error('an error')

    l.check(
        ('root', 'INFO', 'a message'),
        ('root', 'ERROR', 'an error'),
        )

Manual usage

>>> from testfixtures import LogCapture
>>> l = LogCapture()

After which you can also "check" the logs:

>>> l.check(('root', 'INFO', 'a message'))
<...>

EDIT: To access specific logs and analyze them in a custom way, you can just iterate through l.records (where l is just LogCapture's instance) and access some properties of each of them (eg. msg contains message sent to logger, levelname contains codename of the level, and there are plenty other properties).

like image 139
Tadeck Avatar answered Oct 19 '22 18:10

Tadeck