test-webkitpy: handle failures properly when running in parallel
authordpranke@chromium.org <dpranke@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 16 Jul 2012 21:06:28 +0000 (21:06 +0000)
committerdpranke@chromium.org <dpranke@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 16 Jul 2012 21:06:28 +0000 (21:06 +0000)
https://bugs.webkit.org/show_bug.cgi?id=91416

Reviewed by Tony Chang.

It turns out that unittest.TestResults contain a handle to the
test method itself, which isn't picklable; it's sufficient to just
store the test name instead of the actual method. By doing so
we can move the test_name() method from the printer to the
runner where it belongs (so the printer is less dependent on the
unittest framework's data structures).

This change should really have a test but I don't know how to
write one that properly captures the behavior and won't cause
test-webkitpy itself to fail. I've verified the fix by hand, at
least, in the meantime.

* Scripts/webkitpy/test/printer.py:
(Printer.__init__):
(Printer.print_result):
* Scripts/webkitpy/test/runner.py:
(_test_name):
(Runner.all_test_names):
(_Worker.handle):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@122759 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Tools/ChangeLog
Tools/Scripts/webkitpy/test/printer.py
Tools/Scripts/webkitpy/test/runner.py

index 1d06a76..b06a18a 100644 (file)
@@ -1,5 +1,32 @@
 2012-07-16  Dirk Pranke  <dpranke@chromium.org>
 
+        test-webkitpy: handle failures properly when running in parallel
+        https://bugs.webkit.org/show_bug.cgi?id=91416
+
+        Reviewed by Tony Chang.
+
+        It turns out that unittest.TestResults contain a handle to the
+        test method itself, which isn't picklable; it's sufficient to just
+        store the test name instead of the actual method. By doing so
+        we can move the test_name() method from the printer to the
+        runner where it belongs (so the printer is less dependent on the
+        unittest framework's data structures).
+
+        This change should really have a test but I don't know how to
+        write one that properly captures the behavior and won't cause
+        test-webkitpy itself to fail. I've verified the fix by hand, at
+        least, in the meantime.
+
+        * Scripts/webkitpy/test/printer.py:
+        (Printer.__init__):
+        (Printer.print_result):
+        * Scripts/webkitpy/test/runner.py:
+        (_test_name):
+        (Runner.all_test_names):
+        (_Worker.handle):
+
+2012-07-16  Dirk Pranke  <dpranke@chromium.org>
+
         test-webkitpy: run tests in parallel
         https://bugs.webkit.org/show_bug.cgi?id=91294
 
index 1805978..53f7e53 100644 (file)
@@ -22,7 +22,6 @@
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 import logging
-import re
 import StringIO
 
 from webkitpy.common.system import outputcapture
@@ -34,11 +33,6 @@ class Printer(object):
     def __init__(self, stream, options=None):
         self.stream = stream
         self.options = options
-        self.test_description = re.compile("(\w+) \(([\w.]+)\)")
-
-    def test_name(self, test):
-        m = self.test_description.match(str(test))
-        return "%s.%s" % (m.group(2), m.group(1))
 
     def configure(self, options):
         self.options = options
@@ -126,17 +120,17 @@ class Printer(object):
     def print_result(self, result, run_time):
         self.stream.write('\n')
 
-        for (test, err) in result.errors:
+        for (test_name, err) in result.errors:
             self.stream.write("=" * 80 + '\n')
-            self.stream.write("ERROR: " + self.test_name(test) + '\n')
+            self.stream.write("ERROR: " + test_name + '\n')
             self.stream.write("-" * 80 + '\n')
             for line in err.splitlines():
                 self.stream.write(line + '\n')
             self.stream.write('\n')
 
-        for (test, failure) in result.failures:
+        for (test_name, failure) in result.failures:
             self.stream.write("=" * 80 + '\n')
-            self.stream.write("FAILURE: " + self.test_name(test) + '\n')
+            self.stream.write("FAILURE: " + test_name + '\n')
             self.stream.write("-" * 80 + '\n')
             for line in failure.splitlines():
                 self.stream.write(line + '\n')
index f8f19b2..8c415de 100644 (file)
@@ -23,6 +23,7 @@
 """code to actually run a list of python tests."""
 
 import logging
+import re
 import time
 import unittest
 
@@ -31,6 +32,14 @@ from webkitpy.common import message_pool
 _log = logging.getLogger(__name__)
 
 
+_test_description = re.compile("(\w+) \(([\w.]+)\)")
+
+
+def _test_name(test):
+    m = _test_description.match(str(test))
+    return "%s.%s" % (m.group(2), m.group(1))
+
+
 class Runner(object):
     def __init__(self, printer, options, loader):
         self.options = options
@@ -45,7 +54,7 @@ class Runner(object):
             for t in suite._tests:
                 names.extend(self.all_test_names(t))
         else:
-            names.append(self.printer.test_name(suite))
+            names.append(_test_name(suite))
         return names
 
     def run(self, suite):
@@ -80,4 +89,12 @@ class _Worker(object):
         start = time.time()
         self._caller.post('started_test', test_name)
         self._loader.loadTestsFromName(test_name, None).run(result)
+
+        # The tests in the TestResult contain file objects and other unpicklable things; we only
+        # care about the test name, so we rewrite the result to replace the test with the test name.
+        # FIXME: We need an automated test for this, but I don't know how to write an automated
+        # test that will fail in this case that doesn't get picked up by test-webkitpy normally :(.
+        result.failures = [(_test_name(failure[0]), failure[1]) for failure in result.failures]
+        result.errors = [(_test_name(error[0]), error[1]) for error in result.errors]
+
         self._caller.post('finished_test', test_name, time.time() - start, result)