| 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 |