Bug 1416410 - Record wdspec harness outcomes. r?jgraham
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
--- a/testing/web-platform/tests/tools/wptrunner/wptrunner/executors/base.py
+++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/executors/base.py
@@ -352,22 +352,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,71 @@ 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)
+ try:
+ 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=[harness, subtests])
+ except Exception as e:
+ harness.outcome = ("ERROR", str(e))
+
+ 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":