6

I'd like to test logger messages without printing them to the screen in my unittests. Given this code:

 import logging
 logging.basicConfig(level=logging.ERROR)
 logger = logging.getLogger('test')
 logger.warning('this is a warning')

 # How do I see that there was a warning?

How do I look at the log records in the logger to see that there was a warning? I cannot find an iterator in Logger that would do the job.

Ray Salemi
  • 5,247
  • 4
  • 30
  • 63

1 Answers1

14

You may need to use TestCase.assertLogs() context manager in such case. The documentation provides a pretty good example of what can be done with it:

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'])

Inside the context manager, you can access cm.records for a list of LogRecord instances, or cm.output for a list of formatted messages

Antwane
  • 20,760
  • 7
  • 51
  • 84
  • This is perfect. Thank you! – Ray Salemi May 23 '18 at 16:03
  • See https://stackoverflow.com/a/29938398/498463 for a python 2.7 compatible equivalent of this – John Aug 13 '20 at 16:02
  • I had to drop the 'foo' argument for my test to work. As in '''with self.assertLogs( level='INFO') as cm:''' – mb_atx Apr 26 '21 at 21:47
  • 1
    @mb_atx 'foo' is obviously an example name... You have to replace with your own. In your case, removing the argument will capture logs from RootLogger (a.k.a all logs). It works but the assertion may be too broad. Filter with the name of the logger that is supposed to send log mesages and you will be done – Antwane Apr 27 '21 at 07:12