Created
September 27, 2010 10:19
-
-
Save vsajip/598834 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
# Copyright (C) 2010 Vinay Sajip. All Rights Reserved. | |
# | |
# Permission to use, copy, modify, and distribute this software and its | |
# documentation for any purpose and without fee is hereby granted, | |
# provided that the above copyright notice appear in all copies and that | |
# both that copyright notice and this permission notice appear in | |
# supporting documentation, and that the name of Vinay Sajip | |
# not be used in advertising or publicity pertaining to distribution | |
# of the software without specific, written prior permission. | |
# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING | |
# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL | |
# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR | |
# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER | |
# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT | |
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
# | |
import logging | |
from logging.handlers import BufferingHandler | |
import unittest | |
class TestHandler(BufferingHandler): | |
def __init__(self, matcher): | |
# BufferingHandler takes a "capacity" argument | |
# so as to know when to flush. As we're overriding | |
# shouldFlush anyway, we can set a capacity of zero. | |
# You can call flush() manually to clear out the | |
# buffer. | |
BufferingHandler.__init__(self, 0) | |
self.matcher = matcher | |
def shouldFlush(self): | |
return False | |
def emit(self, record): | |
self.format(record) | |
self.buffer.append(record.__dict__) | |
def matches(self, **kwargs): | |
""" | |
Look for a saved dict whose keys/values match the supplied arguments. | |
""" | |
result = False | |
for d in self.buffer: | |
if self.matcher.matches(d, **kwargs): | |
result = True | |
break | |
return result | |
class Matcher(object): | |
_partial_matches = ('msg', 'message') | |
def matches(self, d, **kwargs): | |
""" | |
Try to match a single dict with the supplied arguments. | |
Keys whose values are strings and which are in self._partial_matches | |
will be checked for partial (i.e. substring) matches. You can extend | |
this scheme to (for example) do regular expression matching, etc. | |
""" | |
result = True | |
for k in kwargs: | |
v = kwargs[k] | |
dv = d.get(k) | |
if not self.match_value(k, dv, v): | |
result = False | |
break | |
return result | |
def match_value(self, k, dv, v): | |
""" | |
Try to match a single stored value (dv) with a supplied value (v). | |
""" | |
if type(v) != type(dv): | |
result = False | |
elif type(dv) is not str or k not in self._partial_matches: | |
result = (v == dv) | |
else: | |
result = dv.find(v) >= 0 | |
return result | |
class LoggingTest(unittest.TestCase): | |
def setUp(self): | |
self.handler = h = TestHandler(Matcher()) | |
self.logger = l = logging.getLogger() | |
l.addHandler(h) | |
def tearDown(self): | |
self.logger.removeHandler(self.handler) | |
self.handler.close() | |
def test_simple(self): | |
"Simple test of logging test harness." | |
# Just as a demo, let's log some messages. | |
# Only one should show up in the log. | |
self.logger.debug("This won't show up.") | |
self.logger.info("Neither will this.") | |
self.logger.warning("But this will.") | |
h = self.handler | |
self.assertTrue(h.matches(levelno=logging.WARNING)) | |
self.assertFalse(h.matches(levelno=logging.DEBUG)) | |
self.assertFalse(h.matches(levelno=logging.INFO)) | |
def test_partial(self): | |
"Test of partial matching in logging test harness." | |
# Just as a demo, let's log some messages. | |
# Only one should show up in the log. | |
self.logger.debug("This won't show up.") | |
self.logger.info("Neither will this.") | |
self.logger.warning("But this will.") | |
h = self.handler | |
self.assertTrue(h.matches(msg="ut th")) # from "But this will" | |
self.assertTrue(h.matches(message="ut th")) # from "But this will" | |
self.assertFalse(h.matches(message="either")) | |
self.assertFalse(h.matches(message="won't")) | |
def test_multiple(self): | |
"Test of matching multiple values in logging test harness." | |
# Just as a demo, let's log some messages. | |
# Only one should show up in the log. | |
self.logger.debug("This won't show up.") | |
self.logger.info("Neither will this.") | |
self.logger.warning("But this will.") | |
self.logger.error("And so will this.") | |
h = self.handler | |
self.assertTrue(h.matches(levelno=logging.WARNING, | |
funcName='test_multiple')) | |
self.assertTrue(h.matches(levelno=logging.ERROR, | |
funcName='test_multiple')) | |
self.assertFalse(h.matches(levelno=logging.INFO)) | |
if __name__ == '__main__': | |
unittest.main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment