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

mockingnosepythonunit-testing

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…

Best Solution

From python 3.4 on, the standard unittest library offers a new test assertion context manager, assertLogs. From the docs:

with self.assertLogs('foo', level='INFO') as cm:
    logging.getLogger('foo').info('first message')
    logging.getLogger('foo.bar').error('second message')
    self.assertEqual(cm.output, ['INFO:foo:first message',
                                 'ERROR:foo.bar:second message'])