[Wtr-development] automatic waiting?

Jari Bakken jari.bakken at gmail.com
Tue Oct 19 17:38:27 EDT 2010

On Mon, Oct 18, 2010 at 3:10 AM, Ethan <notethan at gmail.com> wrote:
> I also think that this should happen in #initialize, and not in
> #assert_exists - it should only happen once at the beginning, not whenever
> you try to do anything with an element.

Actually both watir-webdriver and celerity keeps the lazy locate semantics but
will cache the result of #locate. So the lookup only happens once, not
every time #assert_exists is called.

I can't recall if this was ever added to Watir, but I guess not based
on your comments here.
The caching has some minor drawbacks (i.e. element objects becoming
obsolete - which has caused suprisingly less confusion among users
than I had anticipated), but it avoids the problem of repeatedly
waiting. This could probably be the subject of a whole other thread

On Mon, Oct 18, 2010 at 7:10 PM, Jarmo <jarmo.p at gmail.com> wrote:
> Jari: does that implicit wait in WD mean that 1.5 seconds is waited
> everytime before throwing out an Exception? This is not what i'd want.

I fell off around here.

If the element never appears, then yes WebDriver will raise an
exception. In watir(-webdriver), Element#exists? never raises any
exceptions of course. Why is this not what you want? I don't think
it's unreasonable to provide configurable implicit waits and let
people use wait_until (or element.wait_while_present) when they want
to make sure elements disappear.

> After giving some more thought about it then i cannot see any perfect
> solution to it and i'm starting to believe that there are none :(
> To give you a better picture of the current situation then this is
> what i have to do currently in my tests for example:
> button.click
> # some javascript work
> wait_until {div.exists?)
> button.click
> # some javascript work
> wait_until {div.visible?}
> button.click
> # some javascript work
> wait_until {div.text == "expected text"}
> button.click
> # some javascript work
> wait_until {not div.exists?}

Page objects would make the above much neater, since you can hide all
the waiting logic in the pages/components where they are required.

> And i would like to do these examples like this with RSpec:
> button.click
> # some javascript work
> div.should exist
> button.click
> # some javascript work
> div.should be_visible

This is hiding too much for my taste - it's much better to be explicit
about how/what to wait for when interacting with *the browser tool*.
If this makes your tests look ugly, then it's time to add another
abstraction - page objects - not try to make the browser tool guess
what you're really after.

I liked Ethan's idea of creating an RSpec matcher, i.e.:

  div.should eventually_exist
  div.should eventually_be_visible

The implementation should be super simple (and a collection of such
matchers could be provided in a separate gem).

> button.click
> # some javascript work
> div.text.should == "expected text"

  div(:text => "expected").should eventually_exist

or using the existing wait stuff

  div.when_present.text.should == "expected text"

> button.click
> # some javascript work
> div.should_not exist

 div.should eventually_not_exist

In general, I dislike waiting for things to go away - it very often
leads to hard-to-debug race conditions. Better to wait for the stuff
you want to interact with to be present. It's not always possible, but
should be much rarer than the opposite case.

On Tue, Oct 19, 2010 at 7:05 PM, Jarmo <jarmo.p at gmail.com> wrote:
> This means you could do in Test::Unit
> assert div.not_exists?
> instead of
> assert !div.exists?
> With RSpec you'd have to use a slightly different syntax than usually:
> div.should not_exist # (normally you'd use div.should_not exist)

Really? I agree with Ethan. This is just way too confusing - without
adding very much value over what we have.

> Then it could be possible to set that timeout to let's say 2 seconds
> and you could use "div.should exist" which would wait maximum of 2
> seconds before failing if the div doesn't exist. If div exists then it
> will take as much time as it is taking now.

This is exactly what WebDriver does.

> In the future we could start displaying deprecation warnings if
> timeout stays at 0 - this means that users are not taking advantage of
> that automatic waiting feature and after few versions we could set
> that timeout to something else than 0 by default.

Why would the default ever change from 0? I'm strongly against this -
the default should encourage explicit waiting IMO, which are *always*
more robust.

> What do you guys think about that not-so-perfect-solution? Do you have
> any better ideas?

Be explicit about what you need from the browser. Use abstractions to
make your test code communicate.

Otherwise, I'm keen to keep the API as simple as possible, so if we
need to add something for this I would rather have:


and some (custom) RSpec matchers:

element.should appear
element.should disappear


PS. I'll be travelling and won't be able to follow up this thread much
in the coming days.

More information about the Wtr-development mailing list