Search code examples
pythonunit-testingmockingnose

How should I verify a log message when testing Python code under nose?


I'm trying to write a simple unit test that will verify that, under a certain condition, a class in my application will log an error via the standard logging API. I can't work out what the cleanest way to test this situation is.

I know that nose already captures logging output through it's logging plugin, but this seems to be intended as a reporting and debugging aid for failed tests.

The two ways to do this I can see are:

  • Mock out the logging module, either in a piecemeal way (mymodule.logging = mockloggingmodule) or with a proper mocking library.
  • Write or use an existing nose plugin to capture the output and verify it.

If I go for the former approach, I'd like to know what the cleanest way to reset the global state to what it was before I mocked out the logging module.

Looking forward to your hints and tips on this one...


Solution

  • I used to mock loggers, but in this situation I found best to use logging handlers, so I wrote this one based on the document suggested by jkp(now dead, but cached on Internet Archive)

    class MockLoggingHandler(logging.Handler):
        """Mock logging handler to check for expected logs."""
    
        def __init__(self, *args, **kwargs):
            self.reset()
            logging.Handler.__init__(self, *args, **kwargs)
    
        def emit(self, record):
            self.messages[record.levelname.lower()].append(record.getMessage())
    
        def reset(self):
            self.messages = {
                'debug': [],
                'info': [],
                'warning': [],
                'error': [],
                'critical': [],
            }