зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1316622 - New timeouts inteface in Marionette Python client; r=automatedtester
Introduce a new interface for managing timeouts in the Marionette Python client. MozReview-Commit-ID: JHojs7rWBz5 --HG-- extra : rebase_source : 388b8b3f30f07b95bf40edc57d13ffe5a7d5c502
This commit is contained in:
Родитель
0db3d11874
Коммит
57db3d8819
|
@ -17,18 +17,18 @@ from contextlib import contextmanager
|
|||
from decorators import do_process_check
|
||||
from keys import Keys
|
||||
|
||||
import geckoinstance
|
||||
import errors
|
||||
import geckoinstance
|
||||
import transport
|
||||
from timeout import Timeouts
|
||||
|
||||
|
||||
WEBELEMENT_KEY = "ELEMENT"
|
||||
W3C_WEBELEMENT_KEY = "element-6066-11e4-a52e-4f735466cecf"
|
||||
|
||||
|
||||
class HTMLElement(object):
|
||||
"""
|
||||
Represents a DOM Element.
|
||||
"""
|
||||
"""Represents a DOM Element."""
|
||||
|
||||
def __init__(self, marionette, id):
|
||||
self.marionette = marionette
|
||||
|
@ -537,31 +537,44 @@ class Alert(object):
|
|||
class Marionette(object):
|
||||
"""Represents a Marionette connection to a browser or device."""
|
||||
|
||||
CONTEXT_CHROME = 'chrome' # non-browser content: windows, dialogs, etc.
|
||||
CONTEXT_CONTENT = 'content' # browser content: iframes, divs, etc.
|
||||
CONTEXT_CHROME = "chrome" # non-browser content: windows, dialogs, etc.
|
||||
CONTEXT_CONTENT = "content" # browser content: iframes, divs, etc.
|
||||
DEFAULT_SOCKET_TIMEOUT = 60
|
||||
DEFAULT_STARTUP_TIMEOUT = 120
|
||||
DEFAULT_SHUTDOWN_TIMEOUT = 65 # Firefox will kill hanging threads after 60s
|
||||
|
||||
def __init__(self, host='localhost', port=2828, app=None, bin=None,
|
||||
def __init__(self, host="localhost", port=2828, app=None, bin=None,
|
||||
baseurl=None, timeout=None, socket_timeout=DEFAULT_SOCKET_TIMEOUT,
|
||||
startup_timeout=None, **instance_args):
|
||||
"""
|
||||
:param host: address for Marionette connection
|
||||
:param port: integer port for Marionette connection
|
||||
:param baseurl: where to look for files served from Marionette's www directory
|
||||
:param startup_timeout: seconds to wait for a connection with binary
|
||||
:param timeout: time to wait for page load, scripts, search
|
||||
:param socket_timeout: timeout for Marionette socket operations
|
||||
:param bin: path to app binary; if any truthy value is given this will
|
||||
attempt to start a gecko instance with the specified `app`
|
||||
:param app: type of instance_class to use for managing app instance.
|
||||
See marionette_driver.geckoinstance
|
||||
:param instance_args: args to pass to instance_class
|
||||
"""Construct a holder for the Marionette connection.
|
||||
|
||||
Remember to call ``start_session`` in order to initiate the
|
||||
connection and start a Marionette session.
|
||||
|
||||
:param host: Host where the Marionette server listens.
|
||||
Defaults to localhost.
|
||||
:param port: Port where the Marionette server listens.
|
||||
Defaults to port 2828.
|
||||
:param baseurl: Where to look for files served from Marionette's
|
||||
www directory.
|
||||
:param timeout: Dictionary of default page load, script, and
|
||||
implicit wait timeouts. Timeouts in the session are reset
|
||||
to these values whenever ``reset_timeouts`` is called.
|
||||
:param socket_timeout: Timeout for Marionette socket operations.
|
||||
:param startup_timeout: Seconds to wait for a connection with
|
||||
binary.
|
||||
:param bin: Path to browser binary. If any truthy value is given
|
||||
this will attempt to start a Gecko instance with the specified
|
||||
`app`.
|
||||
:param app: Type of ``instance_class`` to use for managing app
|
||||
instance. See ``marionette_driver.geckoinstance``.
|
||||
:param instance_args: Arguments to pass to ``instance_class``.
|
||||
|
||||
"""
|
||||
self.host = host
|
||||
self.port = self.local_port = int(port)
|
||||
self.bin = bin
|
||||
self.default_timeouts = timeout
|
||||
self.instance = None
|
||||
self.session = None
|
||||
self.session_id = None
|
||||
|
@ -569,7 +582,6 @@ class Marionette(object):
|
|||
self.chrome_window = None
|
||||
self.baseurl = baseurl
|
||||
self._test_name = None
|
||||
self.timeout = timeout
|
||||
self.socket_timeout = socket_timeout
|
||||
self.crashed = 0
|
||||
|
||||
|
@ -579,6 +591,8 @@ class Marionette(object):
|
|||
self.instance.start()
|
||||
self.raise_for_port(timeout=startup_timeout)
|
||||
|
||||
self.timeout = Timeouts(self)
|
||||
|
||||
def _create_instance(self, app, instance_args):
|
||||
if not Marionette.is_port_available(self.port, host=self.host):
|
||||
ex_msg = "{0}:{1} is unavailable.".format(self.host, self.port)
|
||||
|
@ -751,21 +765,20 @@ class Marionette(object):
|
|||
raise errors.lookup(error)(message, stacktrace=stacktrace)
|
||||
|
||||
def reset_timeouts(self):
|
||||
"""Resets timeouts to their defaults to the `self.timeout`
|
||||
attribute. If unset, only the page load timeout is reset to
|
||||
30 seconds.
|
||||
"""Resets timeouts to their defaults to the
|
||||
`self.default_timeouts` attribute. If unset, only the page load
|
||||
timeout is reset to 30 seconds.
|
||||
|
||||
"""
|
||||
setters = {"search": "implicit",
|
||||
"script": "script",
|
||||
"page load": "page_load"}
|
||||
|
||||
timeout_types = {"search": self.set_search_timeout,
|
||||
"script": self.set_script_timeout,
|
||||
"page load": self.set_page_load_timeout}
|
||||
|
||||
if self.timeout is not None:
|
||||
for typ, ms in self.timeout:
|
||||
timeout_types[typ](ms)
|
||||
if self.default_timeouts is not None:
|
||||
for typ, ms in self.default_timeouts:
|
||||
setattr(self.timeout, setters[typ], ms)
|
||||
else:
|
||||
self.set_page_load_timeout(30000)
|
||||
self.timeout.page_load = 30
|
||||
|
||||
def check_for_crash(self):
|
||||
"""Check if the process crashed.
|
||||
|
@ -1813,7 +1826,7 @@ class Marionette(object):
|
|||
|
||||
::
|
||||
|
||||
marionette.set_script_timeout(10000) # set timeout period of 10 seconds
|
||||
marionette.timeout.script = 10
|
||||
result = self.marionette.execute_async_script('''
|
||||
// this script waits 5 seconds, and then returns the number 1
|
||||
setTimeout(function() {
|
||||
|
@ -1843,7 +1856,7 @@ class Marionette(object):
|
|||
An HTMLElement instance may be used to call other methods on the
|
||||
element, such as click(). If no element is immediately found, the
|
||||
attempt to locate an element will be repeated for up to the amount of
|
||||
time set by set_search_timeout(). If multiple elements match the given
|
||||
time set by ``timeout.implicit``. If multiple elements match the given
|
||||
criteria, only the first is returned. If no element matches, a
|
||||
NoSuchElementException will be raised.
|
||||
|
||||
|
@ -1870,7 +1883,7 @@ class Marionette(object):
|
|||
An HTMLElement instance may be used to call other methods on the
|
||||
element, such as click(). If no element is immediately found,
|
||||
the attempt to locate an element will be repeated for up to the
|
||||
amount of time set by set_search_timeout().
|
||||
amount of time set by ``timeout.implicit``.
|
||||
|
||||
:param method: The method to use to locate the elements; one
|
||||
of: "id", "name", "class name", "tag name", "css selector",
|
||||
|
|
|
@ -0,0 +1,87 @@
|
|||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
|
||||
import errors
|
||||
|
||||
|
||||
class Timeouts(object):
|
||||
"""Manage timeout settings in the Marionette session.
|
||||
|
||||
Usage::
|
||||
|
||||
marionette = Marionette(...)
|
||||
marionette.start_session()
|
||||
marionette.timeout.page_load = 10
|
||||
marionette.timeout.page_load
|
||||
# => 10
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, marionette):
|
||||
self._marionette = marionette
|
||||
|
||||
def _set(self, name, sec):
|
||||
ms = sec * 1000
|
||||
try:
|
||||
self._marionette._send_message("setTimeouts", {name: ms})
|
||||
except errors.UnknownCommandException:
|
||||
# remove when 55 is stable
|
||||
self._marionette._send_message("timeouts", {"type": name, "ms": ms})
|
||||
|
||||
def _get(self, name):
|
||||
ms = self._marionette._send_message("getTimeouts", key=name)
|
||||
return ms / 1000
|
||||
|
||||
@property
|
||||
def script(self):
|
||||
"""Get the session's script timeout. This specifies the time
|
||||
to wait for injected scripts to finished before interrupting
|
||||
them. It is by default 30 seconds.
|
||||
|
||||
"""
|
||||
return self._get("script")
|
||||
|
||||
@script.setter
|
||||
def script(self, sec):
|
||||
"""Set the session's script timeout. This specifies the time
|
||||
to wait for injected scripts to finish before interrupting them.
|
||||
|
||||
"""
|
||||
self._set("script", sec)
|
||||
|
||||
@property
|
||||
def page_load(self):
|
||||
"""Get the session's page load timeout. This specifies the time
|
||||
to wait for the page loading to complete. It is by default 5
|
||||
minutes (or 300 seconds).
|
||||
|
||||
"""
|
||||
return self._get("page load")
|
||||
|
||||
@page_load.setter
|
||||
def page_load(self, sec):
|
||||
"""Set the session's page load timeout. This specifies the time
|
||||
to wait for the page loading to complete.
|
||||
|
||||
"""
|
||||
self._set("page load", sec)
|
||||
|
||||
@property
|
||||
def implicit(self):
|
||||
"""Get the session's implicit wait timeout. This specifies the
|
||||
time to wait for the implicit element location strategy when
|
||||
retrieving elements. It is by default disabled (0 seconds).
|
||||
|
||||
"""
|
||||
return self._get("implicit")
|
||||
|
||||
@implicit.setter
|
||||
def implicit(self, sec):
|
||||
"""Set the session's implicit wait timeout. This specifies the
|
||||
time to wait for the implicit element location strategy when
|
||||
retrieving elements.
|
||||
|
||||
"""
|
||||
self._set("implicit", sec)
|
|
@ -71,8 +71,12 @@ class Wait(object):
|
|||
"""
|
||||
|
||||
self.marionette = marionette
|
||||
self.timeout = timeout or (self.marionette.timeout and
|
||||
self.marionette.timeout / 1000.0) or DEFAULT_TIMEOUT
|
||||
self.timeout = timeout
|
||||
if self.timeout is None:
|
||||
if self.marionette.default_timeouts is not None:
|
||||
self.timeout = self.marionette.default_timeouts.get("search")
|
||||
else:
|
||||
self.timeout = DEFAULT_TIMEOUT
|
||||
self.clock = clock or SystemClock()
|
||||
self.end = self.clock.now + self.timeout
|
||||
self.interval = interval
|
||||
|
|
|
@ -68,13 +68,6 @@ class TestTimeouts(MarionetteTestCase):
|
|||
setTimeout(function() { callback(true); }, 500);
|
||||
"""))
|
||||
|
||||
def test_invalid_timeout_types(self):
|
||||
for val in [3.14, True, [], {}, "foo"]:
|
||||
print "testing %s" % type(val)
|
||||
self.assertRaises(InvalidArgumentException, self.marionette.set_search_timeout, val)
|
||||
self.assertRaises(InvalidArgumentException, self.marionette.set_script_timeout, val)
|
||||
self.assertRaises(InvalidArgumentException, self.marionette.set_page_load_timeout, val)
|
||||
|
||||
def test_compat_input_types(self):
|
||||
# When using the spec-incompatible input format which we have
|
||||
# for backwards compatibility, it should be possible to send ms
|
||||
|
|
Загрузка…
Ссылка в новой задаче