=== modified file 'buildout.cfg'
--- buildout.cfg	2010-06-17 23:12:31 +0000
+++ buildout.cfg	2010-09-03 15:02:40 +0000
@@ -30,21 +30,22 @@
 distribute = 0.6.10
 docutils = 0.6
 Jinja2 = 2.3.1
-logilab.pylintinstaller = 0.15.2
+logilab-astng = 0.20.1
+logilab-common = 0.51.0
 mocker = 0.10.1
 Pygments = 1.3.1
-pylint = 0.15.2
+pylint = 0.21.2
 Sphinx = 0.6.5
 setuptools = 0.6c9
 z3c.recipe.filetemplate = 2.0.3
 z3c.recipe.sphinxdoc = 0.0.8
 z3c.recipe.tag = 0.3.0
-zc.buildout = 1.5.0dev-gary-r111190
-zc.recipe.egg = 1.2.3dev-gary-r110068
+zc.buildout = 1.5.1
+zc.recipe.egg = 1.3.2
 zc.recipe.testrunner = 1.2.0
 zope.exceptions = 3.5.2
-zope.interface = 3.5.3
-zope.testing = 3.9.4-bug579019
+zope.interface = 3.6.1
+zope.testing = 3.9.5
 
 
 [test]
@@ -77,8 +78,6 @@
 
 [pylint]
 recipe = zc.recipe.egg
-eggs =
-    logilab.pylintinstaller
-    pylint==0.15.2
+eggs = pylint
 entry-points = pylint=pylint.lint:Run
 arguments = sys.argv[1:]

=== modified file 'src/lazr/testing/jstestdriver.py'
--- src/lazr/testing/jstestdriver.py	2010-06-18 02:05:55 +0000
+++ src/lazr/testing/jstestdriver.py	2010-09-03 15:02:40 +0000
@@ -53,6 +53,7 @@
         return "<%s testMethod=%s, browser=%s>" % (self.classname,
                                                    self.name, self.browser)
 
+
 class GlobalJsTestDriverResult(object):
 
     failureException = JsTestDriverFailure
@@ -89,6 +90,7 @@
         self.expat = expat
         self.result = result
         self.test_result = None
+        self.test_results = {}
 
         # attach expat parser methods
         for name, value in type(self).__dict__.items():
@@ -99,6 +101,49 @@
             except AttributeError:
                 pass
 
+    def _add_success(self, test_result):
+        if isinstance(self.result, ZopeTestResult):
+            self.result.options.output.test_success(
+                test_result, float(test_result.duration))
+        else:
+            self.result.addSuccess(test_result)
+
+    def _add_failure(self, test_result):
+        message = test_result.message
+        if message is None:
+            message = test_result.content
+        else:
+            message = [message]
+        try:
+            raise JsTestDriverFailure(message)
+        except:
+            self.result.addFailure(test_result, sys.exc_info())
+
+    def _add_error(self, test_result):
+        message = test_result.message
+        if message is None:
+            message = test_result.content
+        else:
+            message = [message]
+        try:
+            raise JsTestDriverError(message)
+        except:
+            self.result.addError(test_result, sys.exc_info())
+
+    def add_results(self):
+        for test_result, outcome in sorted(
+                self.test_results.items(), key=lambda x: x[0].id()):
+            self.result.startTest(test_result)
+            if outcome == "success":
+                self._add_success(test_result)
+            elif outcome == "failure":
+                self._add_failure(test_result)
+            elif outcome == "error":
+                self._add_error(test_result)
+            else:
+                raise ValueError("Unknown test outcome: %s" % outcome)
+            self.result.stopTest(test_result)
+
     def StartElementHandler(self, tag, attributes):
         if tag == "testsuite":
             pass
@@ -108,7 +153,6 @@
             duration = attributes["time"]
             self.test_result = JsTestDriverResult(classname, name,
                                                   browser, duration)
-            self.result.startTest(self.test_result)
         elif tag in ("error", "failure"):
             self.test_result.failure_type = attributes["type"]
             message = attributes.get("message", None)
@@ -121,32 +165,12 @@
         if tag == "testsuite":
             pass
         elif tag == "testcase":
-            if isinstance(self.result, ZopeTestResult):
-                self.result.options.output.test_success(
-                    self.test_result, float(self.test_result.duration))
-            else:
-                self.result.addSuccess(self.test_result)
-            self.result.stopTest(self.test_result)
+            if self.test_result not in self.test_results:
+                self.test_results[self.test_result] = "success"
         elif tag == "error":
-            message = self.test_result.message
-            if message is None:
-                message = self.test_result.content
-            else:
-                message = [message]
-            try:
-                raise JsTestDriverError(message)
-            except:
-                self.result.addError(self.test_result, sys.exc_info())
+            self.test_results[self.test_result] = "error"
         elif tag == "failure":
-            message = self.test_result.message
-            if message is None:
-                message = self.test_result.content
-            else:
-                message = [message]
-            try:
-                raise JsTestDriverFailure(message)
-            except:
-                self.result.addFailure(self.test_result, sys.exc_info())
+            self.test_results[self.test_result] = "failure"
         else:
             raise ValueError("Unexpected tag: %s" % tag)
 
@@ -316,7 +340,7 @@
     def _reportResults(self, result):
         """Parse generated test results and report them to L{unittest}.
         """
-        for fname in os.listdir(self.output_dir):
+        for fname in sorted(os.listdir(self.output_dir)):
             output = open(os.path.join(self.output_dir, fname), "r")
             try:
                 body = output.read()
@@ -324,8 +348,9 @@
                 output.close()
 
             expat = xml.parsers.expat.ParserCreate()
-            JsTestDriverResultParser(expat, result)
+            parser = JsTestDriverResultParser(expat, result)
             expat.Parse(body, 1)
+            parser.add_results()
 
     def run(self, result=None):
         if result is None:
@@ -340,4 +365,3 @@
 
     def runTest(self):
         self.run()
-

=== modified file 'src/lazr/testing/tests/jstestdriver.txt'
--- src/lazr/testing/tests/jstestdriver.txt	2010-06-18 02:05:55 +0000
+++ src/lazr/testing/tests/jstestdriver.txt	2010-09-03 15:02:40 +0000
@@ -30,15 +30,6 @@
     Running lazr.testing.jstestdriver.JsTestDriverLayer tests:
       Set up lazr.testing.jstestdriver.JsTestDriverLayer in N.NNN seconds.
       Running:
-     testThrowAFit:BrowserN.N.N.N (ErrorInlineTestCase) (N.NNN s)
-    <BLANKLINE>
-    <BLANKLINE>
-    Error in test testThrowAFit:BrowserN.N.N.N (ErrorInlineTestCase)
-    Traceback (most recent call last):
-    ...
-    JsTestDriverError: "A Fit"
-    <BLANKLINE>
-     (N.NNN s)
      testAssertFalse:BrowserN.N.N.N (ErrorInlineTestCase) (N.NNN s)
     <BLANKLINE>
     <BLANKLINE>
@@ -47,7 +38,6 @@
     ...
     JsTestDriverError: y is not defined
     <BLANKLINE>
-     (N.NNN s)
      testAssertNull:BrowserN.N.N.N (ErrorInlineTestCase) (N.NNN s)
     <BLANKLINE>
     <BLANKLINE>
@@ -56,7 +46,14 @@
     ...
     JsTestDriverError: y is not defined
     <BLANKLINE>
-     (N.NNN s)
+     testThrowAFit:BrowserN.N.N.N (ErrorInlineTestCase) (N.NNN s)
+    <BLANKLINE>
+    <BLANKLINE>
+    Error in test testThrowAFit:BrowserN.N.N.N (ErrorInlineTestCase)
+    Traceback (most recent call last):
+    ...
+    JsTestDriverError: "A Fit"
+    <BLANKLINE>
      testThrowAnError:BrowserN.N.N.N (ErrorInlineTestCase) (N.NNN s)
     <BLANKLINE>
     <BLANKLINE>
@@ -65,7 +62,22 @@
     ...
     JsTestDriverError: Some Messy Message
     <BLANKLINE>
-     (N.NNN s)
+     testAssertEquals:BrowserN.N.N.N (ErrorTestCase) (N.NNN s)
+    <BLANKLINE>
+    <BLANKLINE>
+    Error in test testAssertEquals:BrowserN.N.N.N (ErrorTestCase)
+    Traceback (most recent call last):
+    ...
+    JsTestDriverError: y is not defined
+    <BLANKLINE>
+     testAssertTrue:BrowserN.N.N.N (ErrorTestCase) (N.NNN s)
+    <BLANKLINE>
+    <BLANKLINE>
+    Error in test testAssertTrue:BrowserN.N.N.N (ErrorTestCase)
+    Traceback (most recent call last):
+    ...
+    JsTestDriverError: y is not defined
+    <BLANKLINE>
      testAssertFalse:BrowserN.N.N.N (FailureInlineTestCase) (N.NNN s)
     <BLANKLINE>
     <BLANKLINE>
@@ -74,7 +86,6 @@
     ...
     JsTestDriverFailure: Not false? Are you kidding me? expected false but was true
     <BLANKLINE>
-     (N.NNN s)
      testAssertNull:BrowserN.N.N.N (FailureInlineTestCase) (N.NNN s)
     <BLANKLINE>
     <BLANKLINE>
@@ -83,11 +94,6 @@
     ...
     JsTestDriverFailure: I was pretty sure it was null. expected null but was {}
     <BLANKLINE>
-     (N.NNN s)
-     testAssertEquals:BrowserN.N.N.N (SuccessTestCase) (N.NNN s)
-     testAssertTrue:BrowserN.N.N.N (SuccessTestCase) (N.NNN s)
-     testAssertFalse:BrowserN.N.N.N (SuccessInlineTestCase) (N.NNN s)
-     testAssertNull:BrowserN.N.N.N (SuccessInlineTestCase) (N.NNN s)
      testAssertEquals:BrowserN.N.N.N (FailureTestCase) (N.NNN s)
     <BLANKLINE>
     <BLANKLINE>
@@ -96,7 +102,6 @@
     ...
     JsTestDriverFailure: expected "Hello" but was "World!"
     <BLANKLINE>
-     (N.NNN s)
      testAssertTrue:BrowserN.N.N.N (FailureTestCase) (N.NNN s)
     <BLANKLINE>
     <BLANKLINE>
@@ -105,33 +110,18 @@
     ...
     JsTestDriverFailure: How can that possibly be false? expected true but was false
     <BLANKLINE>
-     (N.NNN s)
-     testAssertEquals:BrowserN.N.N.N (ErrorTestCase) (N.NNN s)
-    <BLANKLINE>
-    <BLANKLINE>
-    Error in test testAssertEquals:BrowserN.N.N.N (ErrorTestCase)
-    Traceback (most recent call last):
-    ...
-    JsTestDriverError: y is not defined
-    <BLANKLINE>
-     (N.NNN s)
-     testAssertTrue:BrowserN.N.N.N (ErrorTestCase) (N.NNN s)
-    <BLANKLINE>
-    <BLANKLINE>
-    Error in test testAssertTrue:BrowserN.N.N.N (ErrorTestCase)
-    Traceback (most recent call last):
-    ...
-    JsTestDriverError: y is not defined
-    <BLANKLINE>
-     (N.NNN s)
+     testAssertFalse:BrowserN.N.N.N (SuccessInlineTestCase) (N.NNN s)
+     testAssertNull:BrowserN.N.N.N (SuccessInlineTestCase) (N.NNN s)
+     testAssertEquals:BrowserN.N.N.N (SuccessTestCase) (N.NNN s)
+     testAssertTrue:BrowserN.N.N.N (SuccessTestCase) (N.NNN s)
       Ran 14 tests with 4 failures and 6 errors in N.NNN seconds.
     Tearing down left over layers:
       Tear down lazr.testing.jstestdriver.JsTestDriverLayer in N.NNN seconds.
     <BLANKLINE>
     Tests with errors:
-       testThrowAFit:BrowserN.N.N.N (ErrorInlineTestCase)
        testAssertFalse:BrowserN.N.N.N (ErrorInlineTestCase)
        testAssertNull:BrowserN.N.N.N (ErrorInlineTestCase)
+       testThrowAFit:BrowserN.N.N.N (ErrorInlineTestCase)
        testThrowAnError:BrowserN.N.N.N (ErrorInlineTestCase)
        testAssertEquals:BrowserN.N.N.N (ErrorTestCase)
        testAssertTrue:BrowserN.N.N.N (ErrorTestCase)

=== modified file 'src/lazr/testing/tests/test_js.py'
--- src/lazr/testing/tests/test_js.py	2010-06-17 23:12:31 +0000
+++ src/lazr/testing/tests/test_js.py	2010-09-03 15:02:40 +0000
@@ -22,6 +22,7 @@
     config_filename = os.path.abspath(os.path.join(os.path.dirname(__file__),
                                                    "js", "tests.conf"))
 
+
 class JsTestDriverErrorTests(MockerTestCase):
 
     def setUp(self):
@@ -30,7 +31,7 @@
             "JSTESTDRIVER_SERVER",
             "JSTESTDRIVER_PORT",
             "JSTESTDRIVER_CAPTURE_TIMEOUT",
-            "BROWSER"]
+            "JSTESTDRIVER_BROWSER"]
 
         def cleanup_non_existing_key(some_key):
             try:
@@ -123,7 +124,7 @@
         don't wait for too long.
         """
         os.environ["JSTESTDRIVER_CAPTURE_TIMEOUT"] = "1"
-        os.environ["BROWSER"] = ""
+        os.environ["JSTESTDRIVER_BROWSER"] = ""
         if "JSTESTDRIVER_SERVER" in os.environ:
             del os.environ["JSTESTDRIVER_SERVER"]
         os.environ["JSTESTDRIVER_PORT"] = "4225"

