1 # This Source Code Form is subject to the terms of the Mozilla Public
2 # License, v. 2.0. If a copy of the MPL was not distributed with this
3 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
12 GVE
= "org.mozilla.geckoview_example"
35 old_environ
= os
.environ
.copy()
37 with
TemporaryDirectory() as cache
:
39 os
.environ
.update(environ
)
41 config_plugin
= WDConfig()
42 result_recorder
= ResultRecorder(logger
)
45 "--strict", # turn warnings into errors
46 "-vv", # show each individual subtest and full failure logs
48 "no", # enable stdout/stderr from tests
50 cache
, # temporary directory
51 "--showlocals", # display contents of variables in local scope
53 "no:mozlog", # use the WPT result recorder
57 "no:cacheprovider", # disable state preservation across invocations
58 "-o=console_output_style=classic", # disable test progress bar
65 "--webdriver-ws-port",
73 args
.append("--headless")
76 args
.append("--browser-binary")
77 args
.append(browser_binary
)
80 args
.append("--device-serial")
81 args
.append(device_serial
)
84 args
.append("--package-name")
85 args
.append(package_name
)
88 args
.append("--addon")
96 args
.append("--do2fa")
99 args
.append("--config")
102 if interventions
is not None and shims
is not None:
104 "Must provide only one of interventions or shims argument"
106 elif interventions
is None and shims
is None:
108 "Must provide either an interventions or shims argument"
111 name
= "webcompat-interventions"
112 if interventions
== "enabled":
113 args
.extend(["-m", "with_interventions"])
114 elif interventions
== "disabled":
115 args
.extend(["-m", "without_interventions"])
116 elif interventions
is not None:
117 raise ValueError(f
"Invalid value for interventions {interventions}")
118 if shims
== "enabled":
119 args
.extend(["-m", "with_shims"])
120 name
= "smartblock-shims"
121 elif shims
== "disabled":
122 args
.extend(["-m", "without_shims"])
123 name
= "smartblock-shims"
124 elif shims
is not None:
125 raise ValueError(f
"Invalid value for shims {shims}")
127 name
= "smartblock-shims"
130 args
.extend(["-k", bug
])
134 logger
.suite_start([], name
=name
)
135 pytest
.main(args
, plugins
=[config_plugin
, result_recorder
])
136 except Exception as e
:
137 logger
.critical(str(e
))
142 os
.environ
= old_environ
146 def pytest_addoption(self
, parser
):
148 "--browser-binary", action
="store", help="Path to browser binary"
151 "--webdriver-binary", action
="store", help="Path to webdriver binary"
157 help="Port on which to run WebDriver",
160 "--webdriver-ws-port",
163 help="Port on which to run WebDriver BiDi websocket",
166 "--browser", action
="store", choices
=["firefox"], help="Name of the browser"
168 parser
.addoption("--bug", action
="store", help="Bug number to run tests for")
173 help="Do two-factor auth live in supporting tests",
178 help="Path to JSON file containing logins and other settings",
183 help="Path to the webcompat addon XPI to use",
188 help="Emulator device serial number",
194 help="Android package to run/connect to",
197 "--headless", action
="store_true", help="Run browser in headless mode"
201 class ResultRecorder(object):
202 def __init__(self
, logger
):
205 def pytest_runtest_logreport(self
, report
):
206 if report
.passed
and report
.when
== "call":
207 self
.record_pass(report
)
209 if report
.when
!= "call":
210 self
.record_error(report
)
212 self
.record_fail(report
)
214 self
.record_skip(report
)
216 def record_pass(self
, report
):
217 self
.record(report
.nodeid
, "PASS")
219 def record_fail(self
, report
):
220 # pytest outputs the stacktrace followed by an error message prefixed
223 # def test_example():
224 # > assert "fuu" in "foobar"
225 # > E AssertionError: assert 'fuu' in 'foobar'
227 for line
in report
.longreprtext
.splitlines():
228 if line
.startswith("E "):
229 message
= line
[1:].strip()
232 self
.record(report
.nodeid
, "FAIL", message
=message
, stack
=report
.longrepr
)
234 def record_error(self
, report
):
235 # error in setup/teardown
236 if report
.when
!= "call":
237 message
= "%s error" % report
.when
238 self
.record(report
.nodeid
, "ERROR", message
, report
.longrepr
)
240 def record_skip(self
, report
):
241 self
.record(report
.nodeid
, "SKIP")
243 def record(self
, test
, status
, message
=None, stack
=None):
244 if stack
is not None:
246 self
.logger
.test_start(test
)
247 self
.logger
.test_end(
248 test
=test
, status
=status
, expected
="PASS", message
=message
, stack
=stack
252 class TemporaryDirectory(object):
254 self
.path
= tempfile
.mkdtemp(prefix
="pytest-")
257 def __exit__(self
, *args
):
259 shutil
.rmtree(self
.path
)
261 # no such file or directory
262 if e
.errno
!= errno
.ENOENT
: