Bug 1416410 - Record wdspec harness outcomes. r?jgraham,davehunt draft
authorAndreas Tolfsen <ato@sny.no>
Tue, 14 Nov 2017 12:58:39 -0500
changeset 697818 494af8464b22ae377187799a5ba2d2f800c5397e
parent 697817 934fe0bd60626cd4d8693b2a6788205d7605fa34
child 697819 bd71540075bdc5ab6f50e6b258d1ad2d4d651203
push id89105
push userbmo:ato@sny.no
push dateTue, 14 Nov 2017 19:02:51 +0000
reviewersjgraham, davehunt
bugs1416410
milestone59.0a1
Bug 1416410 - Record wdspec harness outcomes. r?jgraham,davehunt This fixes the problem that wdspec tests fail silently when there is a problem with collecting the file in pytest. For example, if the Python test file contains a SyntaxError we currently fail to record this as ERROR, and instead report it as OK. MozReview-Commit-ID: 5W46gaLQa0c
testing/web-platform/tests/tools/wptrunner/wptrunner/executors/base.py
testing/web-platform/tests/tools/wptrunner/wptrunner/executors/pytestrunner/runner.py
--- a/testing/web-platform/tests/tools/wptrunner/wptrunner/executors/base.py
+++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/executors/base.py
@@ -351,22 +351,20 @@ class WdspecExecutor(TestExecutor):
                                   timeout).run()
 
         if success:
             return self.convert_result(test, data)
 
         return (test.result_cls(*data), [])
 
     def do_wdspec(self, session_config, path, timeout):
-        harness_result = ("OK", None)
-        subtest_results = pytestrunner.run(path,
-                                           self.server_config,
-                                           session_config,
-                                           timeout=timeout)
-        return (harness_result, subtest_results)
+        return pytestrunner.run(path,
+                                self.server_config,
+                                session_config,
+                                timeout=timeout)
 
     def do_delayed_imports(self):
         global pytestrunner
         from . import pytestrunner
 
 
 class Protocol(object):
     def __init__(self, executor, browser):
--- a/testing/web-platform/tests/tools/wptrunner/wptrunner/executors/pytestrunner/runner.py
+++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/executors/pytestrunner/runner.py
@@ -1,9 +1,10 @@
-"""Provides interface to deal with pytest.
+"""
+Provides interface to deal with pytest.
 
 Usage::
 
     session = webdriver.client.Session("127.0.0.1", "4444", "/")
     harness_result = ("OK", None)
     subtest_results = pytestrunner.run("/path/to/test", session.url)
     return (harness_result, subtest_results)
 """
@@ -19,55 +20,68 @@ pytest = None
 
 
 def do_delayed_imports():
     global pytest
     import pytest
 
 
 def run(path, server_config, session_config, timeout=0):
-    """Run Python test at ``path`` in pytest.  The provided ``session``
+    """
+    Run Python test at ``path`` in pytest.  The provided ``session``
     is exposed as a fixture available in the scope of the test functions.
 
     :param path: Path to the test file.
     :param session_config: dictionary of host, port,capabilities parameters
     to pass through to the webdriver session
     :param timeout: Duration before interrupting potentially hanging
         tests.  If 0, there is no timeout.
 
-    :returns: List of subtest results, which are tuples of (test id,
-        status, message, stacktrace).
+    :returns: (<harness result>, [<subtest result>, ...]),
+        where <subtest result> is (test id, status, message, stacktrace).
     """
-
     if pytest is None:
         do_delayed_imports()
 
-    recorder = SubtestResultRecorder()
-
     os.environ["WD_HOST"] = session_config["host"]
     os.environ["WD_PORT"] = str(session_config["port"])
     os.environ["WD_CAPABILITIES"] = json.dumps(session_config["capabilities"])
     os.environ["WD_SERVER_CONFIG"] = json.dumps(server_config)
 
-    plugins = [recorder]
-
-    # TODO(ato): Deal with timeouts
+    harness = HarnessResultRecorder()
+    subtests = SubtestResultRecorder()
 
     with TemporaryDirectory() as cache:
         pytest.main(["--strict",  # turn warnings into errors
                      "--verbose",  # show each individual subtest
                      "--capture", "no",  # enable stdout/stderr from tests
                      "--basetemp", cache,  # temporary directory
                      "--showlocals",  # display contents of variables in local scope
                      "-p", "no:mozlog",  # use the WPT result recorder
                      "-p", "no:cacheprovider",  # disable state preservation across invocations
                      path],
-                    plugins=plugins)
+                    plugins=[harness, subtests])
+
+    return (harness.outcome, subtests.results)
+
 
-    return recorder.results
+class HarnessResultRecorder(object):
+    outcomes = {
+        "failed": "ERROR",
+        "passed": "OK",
+        "skipped": "SKIP",
+    }
+
+    def __init__(self):
+        # we are ok unless told otherwise
+        self.outcome = ("OK", None)
+
+    def pytest_collectreport(self, report):
+        harness_result = self.outcomes[report.outcome]
+        self.outcome = (harness_result, None)
 
 
 class SubtestResultRecorder(object):
     def __init__(self):
         self.results = []
 
     def pytest_runtest_logreport(self, report):
         if report.passed and report.when == "call":