Python + nose: make assertions about logged text?
Is there some simple w开发者_StackOverflow社区ay of capturing and making assertions about logged messages with nose
?
For example, I'd like to be able to do something like:
cook_eggs()
assert_logged("eggs are ready!")
You can create a custom handler which can check for the message being sent through logging. The BufferingHandler is a perfect match for this job.
You might also want to attach in your test the handler to any logger you are using in your code, such as logging.getLogger('foo').addHandler(...)
. You could eventually attach the handler in the setUp
and tearDown
methods of your test case.
import logging
import logging.handlers
class AssertingHandler(logging.handlers.BufferingHandler):
def __init__(self,capacity):
logging.handlers.BufferingHandler.__init__(self,capacity)
def assert_logged(self,test_case,msg):
for record in self.buffer:
s = self.format(record)
if s == msg:
return
test_case.assertTrue(False, "Failed to find log message: " + msg)
def cook_eggs():
logging.warn("eggs are ready!")
import unittest
class TestLogging(unittest.TestCase):
def test(self):
asserting_handler = AssertingHandler(10)
logging.getLogger().addHandler(asserting_handler)
cook_eggs()
asserting_handler.assert_logged(self,"eggs are ready!")
logging.getLogger().removeHandler(asserting_handler)
unittest.main()
This is what "Mock Objects" are for.
You can use a mock version of logging which will properly buffer the log messages so that you can later make assertions about them.
Just FWIW, in datalad project we needed similar functionality but also to just swallow the logs (and possibly introspect). So here came the solution -- swallow_logs context handler: https://github.com/datalad/datalad/blob/master/datalad/utils.py#L296 (currently at b633c9da46ab9cccde3d4767928d167a91857153). So now in the test we do smth like
def test_swallow_logs():
lgr = logging.getLogger('datalad')
with swallow_logs(new_level=9) as cm:
eq_(cm.out, '')
lgr.log(8, "very heavy debug")
eq_(cm.out, '') # not even visible at level 9
lgr.log(9, "debug1")
eq_(cm.out, 'debug1\n') # not even visible at level 9
lgr.info("info")
eq_(cm.out, 'debug1\ninfo\n') # not even visible at level 9
精彩评论