The first change is to strictly define what we mean by "loaded" when
calling "get". There are several different interpretations of this in
our code base right now, and I'd like to pick something that we can
implement consistently. The ideal state would be to wait until the
"onload" event has fired for the frame that we're currently
"switchTo()'d" or the default content if the frame is no more. Since
it's possible that we could miss this event, the alternative would be
to wait until the the document.readyState is "complete" or (if we
wanted to appear fast though more likely to cause tests to be flaky)
"interactive".
The second change is to add an API to allow users to control page timeouts:
driver.manage().timeouts().forPageLoad(long duration, TimeUnit in);
driver.manage().timeouts().forPageLoad(long duration, TimeUnit in,
boolean fatal);
The boolean in the second signature would be to indicate that page
load timeouts should be logged and shouldn't throw a TimeoutException
as it turns out that quite often people don't care whether webdriver
has detected a page load as they're using other signals (such as
implicit/explicit waits) to determine when a page is loaded.
Naturally, the defaults would be to model the existing behaviour.
Your thoughts?
Simon
--
You received this message because you are subscribed to the Google Groups "Selenium Developers" group.
To post to this group, send email to selenium-...@googlegroups.com.
To unsubscribe from this group, send email to selenium-develo...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/selenium-developers?hl=en.
As you can see, there's no standard, and as Eran points out, the
wording on "get" is particularly vague (deliberately, I hasten to add,
cos I had no idea how to measure these things when I started
webdriver)
Simon
--
Patrick Lightbody
+1 (415) 830-5488
Schedule a meeting with me at https://tungle.me/lightbody
Simon
We also implemented something called OperaIdle. For Opera's internal
testing we rely a lot on comparing screenshots. This means we want the
page to have stopped "doing things" before we take the screenshot. We
defined these things as:
* plugin activity (Flash etc.)
* running Ecmascript (JS)
* pending reflows and paints
* any animated images (i.e. gifs)
* pending meta-refreshes
* svg animations
once all these conditions have been done the page can be screenshotted.
However, as you've probably already guessed, a page is often ready
*before* all of these have been satisfied, for us as (e.g) when testing
SVG animations, but more importantly on the web when pretty much every
major site is running some JS constantly, to animate banners or doing
XHR. While it originally seemed as a great way to solve the "page is
ready" problem, it actually takes you further away than the simple
solution.
In response to the managing timeouts proposal, I am in favour. I
remember a couple of times the New York Times site has exceeded our 30s
timeout (it seems to be better now), and I can imagine some other sites
do too. I'm also in favour of being able to specify whether hitting the
timeout is fatal, like Simon says (heh), people often only care if an
element exists, rather than the loading state of the page.
[1]
https://github.com/operasoftware/operadriver/blob/master/protos/window_manager-2.0.proto#L109
In answer to your questions:
1) The firefox driver (and maybe IE too) will wait for "low threshold"
meta redirects to fire if they notice them. A "low threshold" is
generally considered to be 0 or 1 second. The reason for this is that
meta redirects seem to fall into two camps: the "I'd love to do a
server-side redirect, but can't" and the "interstitial page that
reloads periodically as a long running operation completes" The former
tend to have very low meta redirect timeouts, the latter longer.
2) It seems reasonable to apply this time out to any page load, no
matter whether it's triggered by a "get" or a "click". There is the
nasty case of detecting whether a click has actually caused a page
reload when using native events, but that's a different problem to
solve.
3) Generally the problem of page loads falls into two camps: those
where a third party dependency of a page (ads, trackers) respond way
too slowly, causing a page that is otherwise ready to appear inactive
for too long, and those where the app under test is either meant to
have completed responses after a very short or long duration
(typically, people seem keen on extending timeouts) A timeout of some
sort seems to be the major user request.
Control over the mechanism used for determining a page load is
interesting, but I'm unsure of the best way of implementing it
cross-browser (my concern is for those browsers where we have to fall
back to Selenium Core's way of telling that a page is loaded, meaning
that we can't just hook in an event handler for "onload")
Users already have a wealth of ways to determine whether a page is
ready for interactions via the explicit and implicit waits that are
already present, and a simple "wait until the document is interactive
or ready" approach would allow other more sophisticated checks (eg:
"wait until all frames are loaded" becomes a simple case of calling
"switchTo().frame" sequentially) so my initial preference would be to
keep things as simple as can be while still keeping to the principle
of least surprise in the common case.
Simon
Simon
Ross
--
Patrick Lightbody
+1 (415) 830-5488
Schedule a meeting with me at https://tungle.me/lightbody
The advice I'd give the gmail team is to use an explicit wait and some
sort of JS variable to indicate that the site is ready for input.
Simon
Simon
The question I'm asking myself is whether this meets the principle of
least surprise. Lots of people expect a page to be fully loaded (and
JS event handlers hooked in via the "onload" event) once a call to
"get" or Selenium RC's "open" completes. A user who wanted to be able
to interact with a page while loading might be able to set the page
load timeout to 0 and mark the failure of a page to load as non-fatal.
Having said that, I've seen enough tests being very flaky because of
pages taking too long to load, so "onload" may be a little too
generous a time out.
Simon
1: driver.manage().pageLoadedCondition(ExpectedCondition);
2: driver.get(String url, ExpectedCondition);
When 1 is called, any subsequent calls to driver.get(String) (without
specifying an explicit expectedCondition) wait on that
ExpectedCondition, as explicit waits currently do.
We provide a number of pre-defined loaded conditions, which we
support; examples that come to mind:
* return immediately
* readyState=interactive
* readyState=complete
* onload=fired
* allFrames=loaded
* millisecondsHavePassed(ms)
If no condition is passed or has been set using manage, we default to
onload has fired.
It's fairly trivial to create the above ExpectedConditions (except for
allFrames=loaded, but we know how tricky that is anyway).
We start running the ExpectedCondition checks as soon as we can after
the get has started executing.
This way, we make it easy for the same wait conditions to be shared
between implicit and explicit waits, and give access to the DOM for
the user to make up their own mind.
Fundamentally, the overload of get is a convenience over having to put
an explicit wait after every get; I could probably justify adding it
to submit, navigate().back() and navigate().forward(). I would have
more difficulty justifying adding it to click. I definitely couldn't
justify adding it to any other APIs (tbh I feel a bit uncomfortable
with that many overloads as it is, but we are talking about a
convenience here).
We should probably transparently swallow "DOM not yet ready to be
queried" exceptions, but that's it.
Bu a user will not try to start interacting with the elements as quickly as an automated process so are less likely to see issues.
I'm deeply uncomfortable about adding lots of overloaded calls to the
API. It doesn't feel "right" and breaks the aim of trying to keep the
API tight and small. Also, ExpectedCondition is in support because it
requires a third party dependency (guava-libraries) Though that's
nice, I'm not keen on tying core webdriver to a library we're using to
provide functionality that's available from several different
competing libraries.
Simon
These will be incredibly flaky tests unless the user takes care to
control the loading of the extra resources, but that's a vote for
"interactive" on the readyState.
The question I'm asking myself is whether this meets the principle of
least surprise. Lots of people expect a page to be fully loaded (and
JS event handlers hooked in via the "onload" event) once a call to
"get" or Selenium RC's "open" completes. A user who wanted to be able
to interact with a page while loading might be able to set the page
load timeout to 0 and mark the failure of a page to load as non-fatal.
Having said that, I've seen enough tests being very flaky because of
pages taking too long to load, so "onload" may be a little too
generous a time out.
* Add the proposed method to "timeouts". It doesn't seem contentious
and fits neatly with our existing APIs
* Implement a handful of strategies for page loading in the Firefox
driver, selectable with a preference but defaulting to what we have
now.
The strategies will be:
* Wait until the document loader informs us there are no active downloads
* Wait for "onload" in the currently used frame
* Wait for "document.readyState == 'interactive'" in the current frame
* Or "DOMContentLoaded" on older firefoxen
* Wait for "document.readyState == 'complete'" in the current frame
The latter two tie into the document readiness section of HTML5:
http://www.whatwg.org/specs/web-apps/current-work/multipage/dom.html#current-document-readiness
The reason for implementing several strategies is to allow us to try
each of them out on existing tests to see the effect. This is a pretty
fundamental change, so we should be taking care to make sure we know
the impact of what we're about to do.
Simon
The whole discussion has been kicked off by the fact that currently
all the drivers behave differently. I'd love some consistant
behaviour. As for jquery, a quick look says that they already a
combination of what we're thinking of doing, but using "complete"
instead of "interactive"
https://github.com/jquery/jquery/blob/master/src/core.js#L425
https://github.com/jquery/jquery/blob/master/src/core.js#L891
Simon