diff options
Diffstat (limited to 'WebKitTools/Scripts/webkitpy/common/system/logtesting.py')
-rw-r--r-- | WebKitTools/Scripts/webkitpy/common/system/logtesting.py | 258 |
1 files changed, 0 insertions, 258 deletions
diff --git a/WebKitTools/Scripts/webkitpy/common/system/logtesting.py b/WebKitTools/Scripts/webkitpy/common/system/logtesting.py deleted file mode 100644 index e361cb5..0000000 --- a/WebKitTools/Scripts/webkitpy/common/system/logtesting.py +++ /dev/null @@ -1,258 +0,0 @@ -# Copyright (C) 2010 Chris Jerdonek (cjerdonek@webkit.org) -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# -# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND -# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -# DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR -# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -"""Supports the unit-testing of logging code. - -Provides support for unit-testing messages logged using the built-in -logging module. - -Inherit from the LoggingTestCase class for basic testing needs. For -more advanced needs (e.g. unit-testing methods that configure logging), -see the TestLogStream class, and perhaps also the LogTesting class. - -""" - -import logging -import unittest - - -class TestLogStream(object): - - """Represents a file-like object for unit-testing logging. - - This is meant for passing to the logging.StreamHandler constructor. - Log messages captured by instances of this object can be tested - using self.assertMessages() below. - - """ - - def __init__(self, test_case): - """Create an instance. - - Args: - test_case: A unittest.TestCase instance. - - """ - self._test_case = test_case - self.messages = [] - """A list of log messages written to the stream.""" - - # Python documentation says that any object passed to the StreamHandler - # constructor should support write() and flush(): - # - # http://docs.python.org/library/logging.html#module-logging.handlers - def write(self, message): - self.messages.append(message) - - def flush(self): - pass - - def assertMessages(self, messages): - """Assert that the given messages match the logged messages. - - messages: A list of log message strings. - - """ - self._test_case.assertEquals(messages, self.messages) - - -class LogTesting(object): - - """Supports end-to-end unit-testing of log messages. - - Sample usage: - - class SampleTest(unittest.TestCase): - - def setUp(self): - self._log = LogTesting.setUp(self) # Turn logging on. - - def tearDown(self): - self._log.tearDown() # Turn off and reset logging. - - def test_logging_in_some_method(self): - call_some_method() # Contains calls to _log.info(), etc. - - # Check the resulting log messages. - self._log.assertMessages(["INFO: expected message #1", - "WARNING: expected message #2"]) - - """ - - def __init__(self, test_stream, handler): - """Create an instance. - - This method should never be called directly. Instances should - instead be created using the static setUp() method. - - Args: - test_stream: A TestLogStream instance. - handler: The handler added to the logger. - - """ - self._test_stream = test_stream - self._handler = handler - - @staticmethod - def _getLogger(): - """Return the logger being tested.""" - # It is possible we might want to return something other than - # the root logger in some special situation. For now, the - # root logger seems to suffice. - return logging.getLogger() - - @staticmethod - def setUp(test_case, logging_level=logging.INFO): - """Configure logging for unit testing. - - Configures the root logger to log to a testing log stream. - Only messages logged at or above the given level are logged - to the stream. Messages logged to the stream are formatted - in the following way, for example-- - - "INFO: This is a test log message." - - This method should normally be called in the setUp() method - of a unittest.TestCase. See the docstring of this class - for more details. - - Returns: - A LogTesting instance. - - Args: - test_case: A unittest.TestCase instance. - logging_level: An integer logging level that is the minimum level - of log messages you would like to test. - - """ - stream = TestLogStream(test_case) - handler = logging.StreamHandler(stream) - handler.setLevel(logging_level) - formatter = logging.Formatter("%(levelname)s: %(message)s") - handler.setFormatter(formatter) - - # Notice that we only change the root logger by adding a handler - # to it. In particular, we do not reset its level using - # logger.setLevel(). This ensures that we have not interfered - # with how the code being tested may have configured the root - # logger. - logger = LogTesting._getLogger() - logger.addHandler(handler) - - return LogTesting(stream, handler) - - def tearDown(self): - """Assert there are no remaining log messages, and reset logging. - - This method asserts that there are no more messages in the array of - log messages, and then restores logging to its original state. - This method should normally be called in the tearDown() method of a - unittest.TestCase. See the docstring of this class for more details. - - """ - self.assertMessages([]) - logger = LogTesting._getLogger() - logger.removeHandler(self._handler) - - def messages(self): - """Return the current list of log messages.""" - return self._test_stream.messages - - # FIXME: Add a clearMessages() method for cases where the caller - # deliberately doesn't want to assert every message. - - # We clear the log messages after asserting since they are no longer - # needed after asserting. This serves two purposes: (1) it simplifies - # the calling code when we want to check multiple logging calls in a - # single test method, and (2) it lets us check in the tearDown() method - # that there are no remaining log messages to be asserted. - # - # The latter ensures that no extra log messages are getting logged that - # the caller might not be aware of or may have forgotten to check for. - # This gets us a bit more mileage out of our tests without writing any - # additional code. - def assertMessages(self, messages): - """Assert the current array of log messages, and clear its contents. - - Args: - messages: A list of log message strings. - - """ - try: - self._test_stream.assertMessages(messages) - finally: - # We want to clear the array of messages even in the case of - # an Exception (e.g. an AssertionError). Otherwise, another - # AssertionError can occur in the tearDown() because the - # array might not have gotten emptied. - self._test_stream.messages = [] - - -# This class needs to inherit from unittest.TestCase. Otherwise, the -# setUp() and tearDown() methods will not get fired for test case classes -# that inherit from this class -- even if the class inherits from *both* -# unittest.TestCase and LoggingTestCase. -# -# FIXME: Rename this class to LoggingTestCaseBase to be sure that -# the unittest module does not interpret this class as a unittest -# test case itself. -class LoggingTestCase(unittest.TestCase): - - """Supports end-to-end unit-testing of log messages. - - Sample usage: - - class SampleTest(LoggingTestCase): - - def test_logging_in_some_method(self): - call_some_method() # Contains calls to _log.info(), etc. - - # Check the resulting log messages. - self.assertLog(["INFO: expected message #1", - "WARNING: expected message #2"]) - - """ - - def setUp(self): - self._log = LogTesting.setUp(self) - - def tearDown(self): - self._log.tearDown() - - def logMessages(self): - """Return the current list of log messages.""" - return self._log.messages() - - # FIXME: Add a clearMessages() method for cases where the caller - # deliberately doesn't want to assert every message. - - # See the code comments preceding LogTesting.assertMessages() for - # an explanation of why we clear the array of messages after - # asserting its contents. - def assertLog(self, messages): - """Assert the current array of log messages, and clear its contents. - - Args: - messages: A list of log message strings. - - """ - self._log.assertMessages(messages) |