OLD | NEW |
1 #!/usr/bin/python2.4 | 1 #!/usr/bin/python2.4 |
2 # Copyright 2009, Google Inc. | 2 # Copyright 2009, Google Inc. |
3 # All rights reserved. | 3 # All rights reserved. |
4 # | 4 # |
5 # Redistribution and use in source and binary forms, with or without | 5 # Redistribution and use in source and binary forms, with or without |
6 # modification, are permitted provided that the following conditions are | 6 # modification, are permitted provided that the following conditions are |
7 # met: | 7 # met: |
8 # | 8 # |
9 # * Redistributions of source code must retain the above copyright | 9 # * Redistributions of source code must retain the above copyright |
10 # notice, this list of conditions and the following disclaimer. | 10 # notice, this list of conditions and the following disclaimer. |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
67 self.write("\n") | 67 self.write("\n") |
68 def get(self): | 68 def get(self): |
69 get_data = self.data | 69 get_data = self.data |
70 self.data = "" | 70 self.data = "" |
71 return get_data | 71 return get_data |
72 | 72 |
73 class TestResult(unittest.TestResult): | 73 class TestResult(unittest.TestResult): |
74 """A specialized class that prints formatted text results to a stream. | 74 """A specialized class that prints formatted text results to a stream. |
75 | 75 |
76 """ | 76 """ |
77 separator1 = "=" * 70 | 77 separator1 = "=" * 30 |
78 separator2 = "-" * 70 | 78 separator2 = "-" * 30 |
79 | 79 |
80 def __init__(self, stream, browser): | 80 def __init__(self, stream, browser, verbose): |
81 unittest.TestResult.__init__(self) | 81 unittest.TestResult.__init__(self) |
82 self.stream = stream | 82 self.stream = stream |
83 # Dictionary of start times | 83 # Dictionary of start times |
84 self.start_times = {} | 84 self.start_times = {} |
85 # Dictionary of results | 85 # Dictionary of results |
86 self.results = {} | 86 self.results = {} |
87 self.browser = browser | 87 self.browser = browser |
| 88 self.verbose = verbose |
88 | 89 |
89 def getDescription(self, test): | 90 def getDescription(self, test): |
90 """Gets description of test.""" | 91 """Gets description of test.""" |
91 return test.shortDescription() or str(test) | 92 return test.shortDescription() or str(test) |
92 | 93 |
93 def startTest(self, test): | 94 def startTest(self, test): |
94 """Starts test.""" | 95 """Starts test.""" |
95 # Records the start time | 96 # Records the start time |
96 self.start_times[test] = time.time() | 97 self.start_times[test] = time.time() |
97 # Default testresult if success not called | 98 # Default testresult if success not called |
98 self.results[test] = "FAIL" | 99 self.results[test] = "FAIL" |
99 unittest.TestResult.startTest(self, test) | 100 unittest.TestResult.startTest(self, test) |
100 self.stream.writeln() | 101 if self.verbose: |
101 self.stream.writeln(self.separator2) | 102 self.stream.writeln() |
102 self.stream.write(self.getDescription(test)) | 103 self.stream.writeln(self.separator2) |
103 self.stream.writeln(" ... ") | 104 self.stream.write(self.getDescription(test)) |
| 105 self.stream.writeln(" ... ") |
104 | 106 |
105 def stopTest(self, test): | 107 def stopTest(self, test): |
106 """Called when test is ended.""" | 108 """Called when test is ended.""" |
107 time_taken = time.time() - self.start_times[test] | 109 time_taken = time.time() - self.start_times[test] |
108 result = self.results[test] | 110 result = self.results[test] |
109 self.stream.writeln("SELENIUMRESULT %s <%s> [%.3fs]: %s" | 111 self.stream.writeln("SELENIUMRESULT %s <%s> [%.3fs]: %s" |
110 % (test, self.browser, time_taken, result)) | 112 % (test, self.browser, time_taken, result)) |
| 113 self.printErrors() |
111 | 114 |
112 def addSuccess(self, test): | 115 def addSuccess(self, test): |
113 """Adds success result to TestResult.""" | 116 """Adds success result to TestResult.""" |
114 unittest.TestResult.addSuccess(self, test) | 117 unittest.TestResult.addSuccess(self, test) |
115 self.results[test] = "PASS" | 118 self.results[test] = "PASS" |
116 | 119 |
117 def addError(self, test, err): | 120 def addError(self, test, err): |
118 """Adds error result to TestResult.""" | 121 """Adds error result to TestResult.""" |
119 unittest.TestResult.addError(self, test, err) | 122 unittest.TestResult.addError(self, test, err) |
120 self.results[test] = "FAIL" | 123 self.results[test] = "FAIL" |
121 | 124 |
122 def addFailure(self, test, err): | 125 def addFailure(self, test, err): |
123 """Adds failure result to TestResult.""" | 126 """Adds failure result to TestResult.""" |
124 unittest.TestResult.addFailure(self, test, err) | 127 unittest.TestResult.addFailure(self, test, err) |
125 self.results[test] = "FAIL" | 128 self.results[test] = "FAIL" |
126 | 129 |
127 def noResponse(self, test): | 130 def noResponse(self, test): |
128 """Configures the result for a test that did not respond.""" | 131 """Configures the result for a test that did not respond.""" |
129 self.results[test] = "FAIL" | 132 self.results[test] = "FAIL" |
130 self.testsRun += 1 | 133 self.testsRun += 1 |
131 self.errors.append("No response from test") | 134 self.errors.append("No response from test") |
132 | 135 |
133 self.stream.writeln() | 136 if self.verbose: |
134 self.stream.writeln(self.separator2) | 137 self.stream.writeln() |
135 self.stream.write(self.getDescription(test)) | 138 self.stream.writeln(self.separator2) |
136 self.stream.writeln(" ... ") | 139 self.stream.write(self.getDescription(test)) |
137 self.stream.writeln("SELENIUMRESULT %s <%s> [?s]: FAIL (HUNG?)" | 140 self.stream.writeln(" ... ") |
| 141 self.stream.writeln("SELENIUMRESULT %s <%s> [0s]: FAIL" |
138 % (test, self.browser)) | 142 % (test, self.browser)) |
139 self.stream.writeln() | 143 self.stream.writeln("Test was aborted due to timeout") |
140 | 144 |
141 def printErrors(self): | 145 def printErrors(self): |
142 """Prints all errors and failures.""" | 146 """Prints all errors and failures.""" |
143 self.stream.writeln() | 147 if self.errors: |
144 self.printErrorList("ERROR", self.errors) | 148 self.printErrorList("ERROR", self.errors) |
145 self.printErrorList("FAIL", self.failures) | 149 if self.failures: |
| 150 self.printErrorList("FAIL", self.failures) |
146 | 151 |
147 def printErrorList(self, flavour, errors): | 152 def printErrorList(self, flavour, errors): |
148 """Prints a given list of errors.""" | 153 """Prints a given list of errors.""" |
149 for test, err in errors: | 154 for test, err in errors: |
150 self.stream.writeln("%s:" % flavour) | 155 self.stream.writeln("%s:" % flavour) |
151 self.stream.writeln("%s" % err) | 156 self.stream.writeln("%s" % err) |
152 | 157 |
153 def printAll(self, stream): | 158 def printAll(self, stream): |
154 """Prints the entire stream to the given stream.""" | 159 """Prints the entire stream to the given stream.""" |
155 stream.write(self.stream.data) | 160 stream.write(self.stream.data) |
(...skipping 12 matching lines...) Expand all Loading... |
168 | 173 |
169 class TestRunnerThread(threading.Thread): | 174 class TestRunnerThread(threading.Thread): |
170 """Abstract test runner class. Launches its own thread for running tests. | 175 """Abstract test runner class. Launches its own thread for running tests. |
171 Formats test results. | 176 Formats test results. |
172 | 177 |
173 Members: | 178 Members: |
174 completely_done_event: event that occurs just before thread exits. | 179 completely_done_event: event that occurs just before thread exits. |
175 test: the currently running test. | 180 test: the currently running test. |
176 browser: selenium_name of browser that will be tested. | 181 browser: selenium_name of browser that will be tested. |
177 """ | 182 """ |
178 def __init__(self): | 183 def __init__(self, verbose): |
179 threading.Thread.__init__(self) | 184 threading.Thread.__init__(self) |
180 # This thread is a daemon so that the program can exit even if the | 185 # This thread is a daemon so that the program can exit even if the |
181 # thread has not finished. | 186 # thread has not finished. |
182 self.setDaemon(True) | 187 self.setDaemon(True) |
183 self.completely_done_event = threading.Event() | 188 self.completely_done_event = threading.Event() |
184 self.test_copy = None | 189 self.test = None |
185 self.browser = "default_browser" | 190 self.browser = "default_browser" |
| 191 self.verbose = verbose |
186 | 192 |
187 def IsCompletelyDone(self): | 193 def IsCompletelyDone(self): |
188 """Returns true if this test runner is completely done.""" | 194 """Returns true if this test runner is completely done.""" |
189 return self.completely_done_event.isSet() | 195 return self.completely_done_event.isSet() |
190 | 196 |
191 def run(self): | 197 def run(self): |
192 pass | 198 pass |
193 | 199 |
194 def SetBrowser(self, browser): | 200 def SetBrowser(self, browser): |
195 """Sets the browser name.""" | 201 """Sets the browser name.""" |
196 self.browser = browser | 202 self.browser = browser |
197 | 203 |
198 def GetNoResponseResult(self): | 204 def GetNoResponseResult(self): |
199 """Returns a generic no response result for last test.""" | 205 """Returns a generic no response result for last test.""" |
200 result = TestResult(StringBuffer(), self.browser) | 206 result = TestResult(StringBuffer(), self.browser) |
201 result.noResponse(self.test) | 207 result.noResponse(self.test) |
202 return result | 208 return result |
203 | 209 |
204 def RunTest(self, test): | 210 def RunTest(self, test): |
205 "Run the given test case or test suite." | 211 "Run the given test case or test suite." |
206 self.test = test | 212 self.test = test |
207 | 213 |
208 stream = StringBuffer() | 214 stream = StringBuffer() |
209 result = TestResult(stream, self.browser) | 215 result = TestResult(stream, self.browser, self.verbose) |
210 startTime = time.time() | 216 startTime = time.time() |
211 test(result) | 217 test(result) |
212 stopTime = time.time() | 218 stopTime = time.time() |
213 timeTaken = stopTime - startTime | 219 timeTaken = stopTime - startTime |
214 result.printErrors() | 220 if self.verbose: |
| 221 result.printErrors() |
215 run = result.testsRun | 222 run = result.testsRun |
216 stream.writeln("Took %.2fs" % timeTaken) | |
217 stream.writeln() | |
218 return result | 223 return result |
219 | 224 |
220 | 225 |
221 class PDiffTestRunner(TestRunnerThread): | 226 class PDiffTestRunner(TestRunnerThread): |
222 """Test runner for Perceptual Diff tests. Polls a test queue and launches | 227 """Test runner for Perceptual Diff tests. Polls a test queue and launches |
223 given tests. Adds result to given queue. | 228 given tests. Adds result to given queue. |
224 | 229 |
225 Members: | 230 Members: |
226 pdiff_queue: list of tests to run, when they arrive. | 231 pdiff_queue: list of tests to run, when they arrive. |
227 result_queue: queue of our tests results. | 232 result_queue: queue of our tests results. |
228 browser: selenium name of browser to be tested. | 233 browser: selenium name of browser to be tested. |
229 end_testing_event: event that occurs when we are guaranteed no more tests | 234 end_testing_event: event that occurs when we are guaranteed no more tests |
230 will be added to the queue. | 235 will be added to the queue. |
231 """ | 236 """ |
232 def __init__(self, pdiff_queue, result_queue, browser): | 237 def __init__(self, pdiff_queue, result_queue, browser, verbose): |
233 TestRunnerThread.__init__(self) | 238 TestRunnerThread.__init__(self, verbose) |
234 self.pdiff_queue = pdiff_queue | 239 self.pdiff_queue = pdiff_queue |
235 self.result_queue = result_queue | 240 self.result_queue = result_queue |
236 self.browser = browser | 241 self.browser = browser |
237 | 242 |
238 self.end_testing_event = threading.Event() | 243 self.end_testing_event = threading.Event() |
239 | 244 |
240 def EndTesting(self): | 245 def EndTesting(self): |
241 """Called to notify thread that no more tests will be added to the test | 246 """Called to notify thread that no more tests will be added to the test |
242 queue.""" | 247 queue.""" |
243 self.end_testing_event.set() | 248 self.end_testing_event.set() |
(...skipping 27 matching lines...) Expand all Loading... |
271 can_continue_lock: lock for |can_continue|. | 276 can_continue_lock: lock for |can_continue|. |
272 can_continue: is True when main thread permits the test runner to continue. | 277 can_continue: is True when main thread permits the test runner to continue. |
273 sel_builder: builder that constructs new selenium sessions, as needed. | 278 sel_builder: builder that constructs new selenium sessions, as needed. |
274 browser: selenium name of browser to be tested. | 279 browser: selenium name of browser to be tested. |
275 session: current selenium session being used in tests, can be None. | 280 session: current selenium session being used in tests, can be None. |
276 test_queue: queue of tests to run. | 281 test_queue: queue of tests to run. |
277 pdiff_queue: queue of perceptual diff tests to run. We add a perceptual | 282 pdiff_queue: queue of perceptual diff tests to run. We add a perceptual |
278 diff test to the queue when the related selenium test passes. | 283 diff test to the queue when the related selenium test passes. |
279 deadline: absolute time of when the test should be done. | 284 deadline: absolute time of when the test should be done. |
280 """ | 285 """ |
281 def __init__(self, sel_builder, browser, test_queue, pdiff_queue): | 286 def __init__(self, sel_builder, browser, test_queue, pdiff_queue, verbose): |
282 TestRunnerThread.__init__(self) | 287 TestRunnerThread.__init__(self, verbose) |
283 | 288 |
284 # Synchronization. | 289 # Synchronization. |
285 self.testing_event = threading.Event() | 290 self.testing_event = threading.Event() |
286 self.finished_event = threading.Event() | 291 self.finished_event = threading.Event() |
287 self.can_continue_lock = threading.Lock() | 292 self.can_continue_lock = threading.Lock() |
288 self.can_continue = False | 293 self.can_continue = False |
289 | 294 |
290 # Selenium variables. | 295 # Selenium variables. |
291 self.sel_builder = sel_builder | 296 self.sel_builder = sel_builder |
292 self.browser = browser | 297 self.browser = browser |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
389 # Add the dependent perceptual diff test. | 394 # Add the dependent perceptual diff test. |
390 self.pdiff_queue.put(pdiff_test) | 395 self.pdiff_queue.put(pdiff_test) |
391 | 396 |
392 except Queue.Empty: | 397 except Queue.Empty: |
393 break | 398 break |
394 | 399 |
395 self._StopSession() | 400 self._StopSession() |
396 self.completely_done_event.set() | 401 self.completely_done_event.set() |
397 | 402 |
398 | 403 |
OLD | NEW |