[SCM] WebKit Debian packaging branch, webkit-1.1, updated. upstream/1.1.22-985-g3c00f00
cjerdonek at webkit.org
cjerdonek at webkit.org
Wed Mar 17 18:31:24 UTC 2010
The following commit has been merged in the webkit-1.1 branch:
commit c115c80b4fcfc0f430e704a5742f12c23594f002
Author: cjerdonek at webkit.org <cjerdonek at webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date: Wed Mar 10 18:31:32 2010 +0000
Refactored and cleaned up the code for unit-testing logging.
Reviewed by Shinichiro Hamaji.
https://bugs.webkit.org/show_bug.cgi?id=35845
* Scripts/webkitpy/init/logtesting.py:
- Added more information to the module docstring.
- Added an assertMessages() method to the UnitTestLogStream
class. This simplifies the calling code.
- Renamed the UnitTestLog class to LogTesting, and reformulated
it as follows:
- Moved the logging configuration code from the __init__
method to a new static setUp() method.
- Documented the __init__ method to be private.
- Improved the code so that the root logger does not have
its logging level changed. Instead we set the handler's
level. This makes the unit testing more unintrusive.
- Updated the assertMessages() method to call the
UnitTestLogStream class's assertMessages() method.
- More fully documented the class.
* Scripts/webkitpy/style/checker.py:
- Added a logger parameter to the configure_logging() method.
This allows us to prevent test messages from being sent
to the root logger during unit testing, which may be
rendering to the screen, etc.
- Simplified the code by removing the _LevelLoggingFilter class.
- Replaced the _LevelLoggingFilter class with a one-line lambda
expression in configure_logging().
* Scripts/webkitpy/style/checker_unittest.py:
- Changed relative imports to absolute to comply more with PEP8.
- In the ConfigureLoggingTest class:
- Changed the setUp() method to prevent test messages from
being propagated to the root logger.
- Changed the _log() method to a data attribute.
- Updated to accommodate changes to logtesting.py.
* Scripts/webkitpy/style_references.py:
- Updated an import statement.
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@55786 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/WebKitTools/ChangeLog b/WebKitTools/ChangeLog
index 519d465..d352274 100644
--- a/WebKitTools/ChangeLog
+++ b/WebKitTools/ChangeLog
@@ -1,3 +1,47 @@
+2010-03-10 Chris Jerdonek <cjerdonek at webkit.org>
+
+ Reviewed by Shinichiro Hamaji.
+
+ Refactored and cleaned up the code for unit-testing logging.
+
+ https://bugs.webkit.org/show_bug.cgi?id=35845
+
+ * Scripts/webkitpy/init/logtesting.py:
+ - Added more information to the module docstring.
+ - Added an assertMessages() method to the UnitTestLogStream
+ class. This simplifies the calling code.
+ - Renamed the UnitTestLog class to LogTesting, and reformulated
+ it as follows:
+ - Moved the logging configuration code from the __init__
+ method to a new static setUp() method.
+ - Documented the __init__ method to be private.
+ - Improved the code so that the root logger does not have
+ its logging level changed. Instead we set the handler's
+ level. This makes the unit testing more unintrusive.
+ - Updated the assertMessages() method to call the
+ UnitTestLogStream class's assertMessages() method.
+ - More fully documented the class.
+
+ * Scripts/webkitpy/style/checker.py:
+ - Added a logger parameter to the configure_logging() method.
+ This allows us to prevent test messages from being sent
+ to the root logger during unit testing, which may be
+ rendering to the screen, etc.
+ - Simplified the code by removing the _LevelLoggingFilter class.
+ - Replaced the _LevelLoggingFilter class with a one-line lambda
+ expression in configure_logging().
+
+ * Scripts/webkitpy/style/checker_unittest.py:
+ - Changed relative imports to absolute to comply more with PEP8.
+ - In the ConfigureLoggingTest class:
+ - Changed the setUp() method to prevent test messages from
+ being propagated to the root logger.
+ - Changed the _log() method to a data attribute.
+ - Updated to accommodate changes to logtesting.py.
+
+ * Scripts/webkitpy/style_references.py:
+ - Updated an import statement.
+
2010-03-10 Evan Martin <evan at chromium.org>
Reviewed by Darin Adler.
diff --git a/WebKitTools/Scripts/webkitpy/init/logtesting.py b/WebKitTools/Scripts/webkitpy/init/logtesting.py
index 6363115..10d00e4 100644
--- a/WebKitTools/Scripts/webkitpy/init/logtesting.py
+++ b/WebKitTools/Scripts/webkitpy/init/logtesting.py
@@ -20,7 +20,16 @@
# 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."""
+"""Supports the unit-testing of logging code.
+
+Provides support for unit-testing messages logged using the built-in
+logging module.
+
+Use the LogTesting class for basic testing needs. For more advanced
+needs (e.g. unit-testing methods that configure logging), see the
+UnitTestLogStream class.
+
+"""
import logging
@@ -30,93 +39,141 @@ class UnitTestLogStream(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):
+ 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.
-class UnitTestLog(object):
+ messages: A list of log message strings.
- """Supports unit-testing logging.
+ """
+ self._test_case.assertEquals(messages, self.messages)
+
+
+class LogTesting(object):
+
+ """Supports end-to-end unit-testing of log messages.
+
+ Sample usage:
- Sample usage:
+ class SampleTest(unittest.TestCase):
- # The following line should go in the setUp() method of a
- # unittest.TestCase. In particular, self is a TestCase instance.
- self._log = UnitTestLog(self)
+ def setUp(self):
+ self._log = LogTesting.setUp(self) # Turn logging on.
- # Call the following in a test method of a unittest.TestCase.
- log = logging.getLogger("webkitpy")
- log.info("message1")
- log.warn("message2")
- self._log.assertMessages(["INFO: message1\n",
- "WARN: message2\n"]) # Should succeed.
+ def tearDown(self):
+ self._log.tearDown() # Turn off and reset logging.
- # The following line should go in the tearDown() method of
- # unittest.TestCase.
- self._log.tearDown()
+ 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_case, logging_level=None):
- """Configure unit test logging, and return an instance.
+ 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 UnitTestLogStream 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.
- This method 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 are formatted in the
- following way, for example--
+ 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.
+ 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: A logging level. Only messages logged at or
- above this level are written to the testing
- log stream. Defaults to logging.INFO.
+ logging_level: An integer logging level that is the minimum level
+ of log messages you would like to test.
"""
- if logging_level is None:
- logging_level = logging.INFO
-
- stream = UnitTestLogStream()
+ stream = UnitTestLogStream(test_case)
handler = logging.StreamHandler(stream)
+ handler.setLevel(logging_level)
formatter = logging.Formatter("%(levelname)s: %(message)s")
handler.setFormatter(formatter)
- logger = logging.getLogger()
- logger.setLevel(logging_level)
+ # 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)
- self._handler = handler
- self._messages = stream.messages
- self._test_case = test_case
-
- def _logger(self):
- """Return the root logger used for logging."""
- return logging.getLogger()
-
- def assertMessages(self, messages):
- """Assert that the given messages match the logged messages."""
- self._test_case.assertEquals(messages, self._messages)
+ return LogTesting(stream, handler)
def tearDown(self):
- """Unconfigure unit test logging.
+ """Restore logging to its original state.
- This should normally be called in the tearDown method of a
- unittest.TestCase
+ This should normally be called in the tearDown() method of a
+ unittest.TestCase. See the docstring of this class for more
+ details.
"""
- logger = self._logger()
+ logger = LogTesting._getLogger()
logger.removeHandler(self._handler)
+
+ def assertMessages(self, messages):
+ """Assert that the given messages match the logged messages.
+
+ messages: A list of log message strings.
+
+ """
+ self._test_stream.assertMessages(messages)
diff --git a/WebKitTools/Scripts/webkitpy/style/checker.py b/WebKitTools/Scripts/webkitpy/style/checker.py
index 92d65d3..f8ba4f5 100644
--- a/WebKitTools/Scripts/webkitpy/style/checker.py
+++ b/WebKitTools/Scripts/webkitpy/style/checker.py
@@ -230,12 +230,12 @@ def check_webkit_style_configuration(options):
# This can use a formatter like the following, for example--
#
# formatter = logging.Formatter("%(name)s: [%(levelname)s] %(message)s")
-def configure_logging(stream):
+def configure_logging(stream, logger=None):
"""Configure logging, and return the list of handlers added.
- Configures the root logger to log INFO messages and higher.
- Formats WARNING messages and above to display the logging level
- and messages strictly below WARNING not to display it.
+ Configures a logger to log INFO messages and higher. Formats WARNING
+ messages and above to display the logging level, and messages strictly
+ below WARNING not to display it.
Returns:
A list of references to the logging handlers added to the root
@@ -248,6 +248,9 @@ def configure_logging(stream):
stream: A file-like object to which to log. The stream must
define an "encoding" data attribute, or else logging
raises an error.
+ logger: A logging.logger instance to configure. This parameter
+ should be used only in unit tests. Defaults to the
+ root logger.
"""
# If the stream does not define an "encoding" data attribute, the
@@ -265,14 +268,19 @@ def configure_logging(stream):
formatter = logging.Formatter("%(levelname)s: %(message)s")
error_handler.setFormatter(formatter)
- # Handles records strictly below logging.WARNING.
+ # Create a logging.Filter instance that only accepts messages
+ # below WARNING (i.e. filters out anything WARNING or above).
+ non_error_filter = logging.Filter()
+ # The filter method accepts a logging.LogRecord instance.
+ non_error_filter.filter = lambda record: record.levelno < logging.WARNING
+
non_error_handler = logging.StreamHandler(stream)
- non_error_filter = _LevelLoggingFilter(logging.WARNING)
non_error_handler.addFilter(non_error_filter)
formatter = logging.Formatter("%(message)s")
non_error_handler.setFormatter(formatter)
- logger = logging.getLogger()
+ if logger is None:
+ logger = logging.getLogger()
logger.setLevel(logging.INFO)
handlers = [error_handler, non_error_handler]
@@ -283,31 +291,6 @@ def configure_logging(stream):
return handlers
-# FIXME: Consider moving this class into a module in webkitpy.init after
-# getting more experience with its use. We want to make sure
-# we have the right API before doing so. For example, we may
-# want to provide a constructor that has both upper and lower
-# bounds, and not just an upper bound.
-class _LevelLoggingFilter(object):
-
- """A logging filter for blocking records at or above a certain level."""
-
- def __init__(self, logging_level):
- """Create a _LevelLoggingFilter.
-
- Args:
- logging_level: The logging level cut-off. Logging levels at
- or above this level will not be logged.
-
- """
- self._logging_level = logging_level
-
- # The logging module requires that this method be defined.
- def filter(self, log_record):
- """Return whether given the LogRecord should be logged."""
- return log_record.levelno < self._logging_level
-
-
# Enum-like idiom
class FileType:
diff --git a/WebKitTools/Scripts/webkitpy/style/checker_unittest.py b/WebKitTools/Scripts/webkitpy/style/checker_unittest.py
index d866663..06bb191 100755
--- a/WebKitTools/Scripts/webkitpy/style/checker_unittest.py
+++ b/WebKitTools/Scripts/webkitpy/style/checker_unittest.py
@@ -38,8 +38,8 @@ import logging
import unittest
import checker as style
-from ..style_references import UnitTestLog
-from ..style_references import UnitTestLogStream
+from webkitpy.style_references import LogTesting
+from webkitpy.style_references import UnitTestLogStream
from checker import _BASE_FILTER_RULES
from checker import _MAX_REPORTS_PER_CATEGORY
from checker import _PATH_RULES_SPECIFIER as PATH_RULES_SPECIFIER
@@ -63,9 +63,19 @@ class ConfigureLoggingTest(unittest.TestCase):
"""Tests the configure_logging() function."""
def setUp(self):
- log_stream = UnitTestLogStream()
-
- self._handlers = configure_logging(log_stream)
+ log_stream = UnitTestLogStream(self)
+ # Use a logger other than the root logger or one prefixed with
+ # webkit so as not to conflict with test-webkitpy logging.
+ logger = logging.getLogger("unittest")
+
+ # Configure the test logger not to pass messages along to the
+ # root logger. This prevents test messages from being
+ # propagated to loggers used by test-webkitpy logging (e.g.
+ # the root logger).
+ logger.propagate = False
+
+ self._handlers = configure_logging(log_stream, logger)
+ self._log = logger
self._log_stream = log_stream
def tearDown(self):
@@ -75,21 +85,16 @@ class ConfigureLoggingTest(unittest.TestCase):
for a unit test does not affect logging in other unit tests.
"""
- # This should be the same as the logger configured in the
- # configure_logging() method.
- logger = logging.getLogger()
+ logger = self._log
for handler in self._handlers:
logger.removeHandler(handler)
- def _log(self):
- return logging.getLogger("webkitpy")
-
def assert_log_messages(self, messages):
"""Assert that the logged messages equal the given messages."""
- self.assertEquals(messages, self._log_stream.messages)
+ self._log_stream.assertMessages(messages)
def test_warning_message(self):
- self._log().warn("test message")
+ self._log.warn("test message")
self.assert_log_messages(["WARNING: test message\n"])
def test_below_warning_message(self):
@@ -97,16 +102,16 @@ class ConfigureLoggingTest(unittest.TestCase):
# In practice, we will probably only be calling log.info(),
# which corresponds to a logging level of 20.
level = logging.WARNING - 1 # Equals 29.
- self._log().log(level, "test message")
+ self._log.log(level, "test message")
self.assert_log_messages(["test message\n"])
def test_debug_message(self):
- self._log().debug("test message")
+ self._log.debug("test message")
self.assert_log_messages([])
def test_two_messages(self):
- self._log().info("message1")
- self._log().info("message2")
+ self._log.info("message1")
+ self._log.info("message2")
self.assert_log_messages(["message1\n", "message2\n"])
@@ -502,7 +507,7 @@ class StyleCheckerCheckFileTest(unittest.TestCase):
"""
def setUp(self):
- self._log = UnitTestLog(self)
+ self._log = LogTesting.setUp(self)
self.got_file_path = None
self.got_handle_style_error = None
self.got_processor = None
diff --git a/WebKitTools/Scripts/webkitpy/style_references.py b/WebKitTools/Scripts/webkitpy/style_references.py
index cb8a985..e57cd0e 100644
--- a/WebKitTools/Scripts/webkitpy/style_references.py
+++ b/WebKitTools/Scripts/webkitpy/style_references.py
@@ -41,7 +41,7 @@
import os
from diff_parser import DiffParser
-from init.logtesting import UnitTestLog
+from init.logtesting import LogTesting
from init.logtesting import UnitTestLogStream
from scm import detect_scm_system
--
WebKit Debian packaging
More information about the Pkg-webkit-commits
mailing list