Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(93)

Side by Side Diff: third_party/WebKit/Tools/Scripts/webkitpy/common/system/logtesting.py

Issue 2578213005: Use underscores to separate words in filenames in webkitpy. (Closed)
Patch Set: Fix check for attribute in output_capture.py. Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 # Copyright (C) 2010 Chris Jerdonek (cjerdonek@webkit.org)
2 #
3 # Redistribution and use in source and binary forms, with or without
4 # modification, are permitted provided that the following conditions
5 # are met:
6 # 1. Redistributions of source code must retain the above copyright
7 # notice, this list of conditions and the following disclaimer.
8 # 2. Redistributions in binary form must reproduce the above copyright
9 # notice, this list of conditions and the following disclaimer in the
10 # documentation and/or other materials provided with the distribution.
11 #
12 # THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND
13 # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
14 # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
15 # DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR
16 # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
17 # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
18 # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
19 # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
20 # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
21 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
22
23 """Supports the unit-testing of logging code.
24
25 Provides support for unit-testing messages logged using the built-in
26 logging module.
27
28 Inherit from the LoggingTestCase class for basic testing needs. For
29 more advanced needs (e.g. unit-testing methods that configure logging),
30 see the TestLogStream class, and perhaps also the LogTesting class.
31 """
32
33 import logging
34 import unittest
35
36
37 class TestLogStream(object):
38 """Represents a file-like object for unit-testing logging.
39
40 This is meant for passing to the logging.StreamHandler constructor.
41 Log messages captured by instances of this object can be tested
42 using self.assertMessages() below.
43 """
44
45 def __init__(self, test_case):
46 """Creates an instance.
47
48 Args:
49 test_case: A unittest.TestCase instance.
50 """
51 self._test_case = test_case
52 self.messages = [] # A list of log messages written to the stream.
53
54 # Python documentation says that any object passed to the StreamHandler
55 # constructor should support write() and flush().
56 #
57 # http://docs.python.org/library/logging.html#module-logging.handlers
58
59 def write(self, message):
60 self.messages.append(message)
61
62 def flush(self):
63 pass
64
65 def assertMessages(self, messages):
66 """Asserts that the given messages match the logged messages."""
67 self._test_case.assertEqual(messages, self.messages)
68
69
70 class LogTesting(object):
71 """Supports end-to-end unit-testing of log messages.
72
73 Sample usage:
74
75 class SampleTest(unittest.TestCase):
76
77 def setUp(self):
78 self._log = LogTesting.setUp(self) # Turn logging on.
79
80 def tearDown(self):
81 self._log.tearDown() # Turn off and reset logging.
82
83 def test_logging_in_some_method(self):
84 call_some_method() # Contains calls to _log.info(), etc.
85
86 # Check the resulting log messages.
87 self._log.assertMessages(["INFO: expected message #1",
88 "WARNING: expected message #2"])
89 """
90
91 def __init__(self, test_stream, handler):
92 """Creates an instance.
93
94 This method should never be called directly. Instances should
95 instead be created using the static setUp() method.
96
97 Args:
98 test_stream: A TestLogStream instance.
99 handler: The handler added to the logger.
100 """
101 self._test_stream = test_stream
102 self._handler = handler
103
104 @staticmethod
105 def _getLogger():
106 """Returns the logger being tested."""
107 # It is possible we might want to return something other than
108 # the root logger in some special situation. For now, the
109 # root logger seems to suffice.
110 return logging.getLogger()
111
112 @staticmethod
113 def setUp(test_case, logging_level=logging.INFO):
114 """Configures logging for unit testing.
115
116 Configures the root logger to log to a testing log stream.
117 Only messages logged at or above the given level are logged
118 to the stream. Messages logged to the stream are formatted
119 in the following way, for example--
120
121 "INFO: This is a test log message."
122
123 This method should normally be called in the setUp() method
124 of a unittest.TestCase. See the docstring of this class
125 for more details.
126
127 Args:
128 test_case: A unittest.TestCase instance.
129 logging_level: An integer logging level that is the minimum level
130 of log messages you would like to test.
131
132 Returns:
133 A LogTesting instance.
134 """
135 stream = TestLogStream(test_case)
136 handler = logging.StreamHandler(stream)
137 handler.setLevel(logging_level)
138 formatter = logging.Formatter("%(levelname)s: %(message)s")
139 handler.setFormatter(formatter)
140
141 # Notice that we only change the root logger by adding a handler
142 # to it. In particular, we do not reset its level using
143 # logger.setLevel(). This ensures that we have not interfered
144 # with how the code being tested may have configured the root
145 # logger.
146 logger = LogTesting._getLogger()
147 logger.setLevel(logging_level)
148 logger.addHandler(handler)
149
150 return LogTesting(stream, handler)
151
152 def tearDown(self):
153 """Resets logging."""
154 logger = LogTesting._getLogger()
155 logger.removeHandler(self._handler)
156
157 def messages(self):
158 """Returns the current list of log messages."""
159 return self._test_stream.messages
160
161 # FIXME: Add a clearMessages() method for cases where the caller
162 # deliberately doesn't want to assert every message.
163
164 def assertMessages(self, messages):
165 """Asserts the current array of log messages, and clear its contents.
166
167 We clear the log messages after asserting since they are no longer
168 needed after asserting. This serves two purposes: (1) it simplifies
169 the calling code when we want to check multiple logging calls in a
170 single test method, and (2) it lets us check in the tearDown() method
171 that there are no remaining log messages to be asserted.
172
173 The latter ensures that no extra log messages are getting logged that
174 the caller might not be aware of or may have forgotten to check for.
175 This gets us a bit more mileage out of our tests without writing any
176 additional code.
177
178 We want to clear the array of messages even in the case of
179 an Exception (e.g. an AssertionError). Otherwise, another
180 AssertionError can occur in the tearDown() because the
181 array might not have gotten emptied.
182
183 Args:
184 messages: A list of log message strings.
185 """
186 try:
187 self._test_stream.assertMessages(messages)
188 finally:
189 self._test_stream.messages = []
190
191
192 class LoggingTestCase(unittest.TestCase):
193
194 """Supports end-to-end unit-testing of log messages.
195
196 This class needs to inherit from unittest.TestCase. Otherwise, the
197 setUp() and tearDown() methods will not get fired for test case classes
198 that inherit from this class -- even if the class inherits from *both*
199 unittest.TestCase and LoggingTestCase.
200
201 Sample usage:
202
203 class SampleTest(LoggingTestCase):
204
205 def test_logging_in_some_method(self):
206 call_some_method() # Contains calls to _log.info(), etc.
207
208 # Check the resulting log messages.
209 self.assertLog(["INFO: expected message #1",
210 "WARNING: expected message #2"])
211 """
212
213 def setUp(self):
214 self._log = LogTesting.setUp(self)
215
216 def tearDown(self):
217 self._log.tearDown()
218
219 def logMessages(self):
220 """Return the current list of log messages."""
221 return self._log.messages()
222
223 # FIXME: Add a clearMessages() method for cases where the caller
224 # deliberately doesn't want to assert every message.
225
226 # See the docstring for LogTesting.assertMessages() for an explanation
227 # of why we clear the array of messages after asserting its contents.
228 def assertLog(self, messages):
229 """Asserts the current array of log messages, and clear its contents."""
230 self._log.assertMessages(messages)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698