[Wtr-development] automatic waiting?

Jarmo jarmo.p at gmail.com
Wed Oct 20 05:22:23 EDT 2010

On Wed, Oct 20, 2010 at 12:38 AM, Jari Bakken <jari.bakken at gmail.com> wrote:
> 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.

so you can't do anything like this?
my_div = div(:id => "something")
my_div.text.should == "something"
my_div.text.should == "something else"

this of course depends what exactly is cached... if #text was cached
then it might not work... of course i don't know the internals of
watir-webdriver so much... if the #text is cached then that caching is
bad. Caching is quite often overused anyway causing more problems than
actually helping. At least i know many projects where problems have
"been solved" by caching without inspecting why something is so slow
in the first place. For me it is rather hiding the real problems
behind the cache to not deal with them :P

> 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.

Yes, my bad. Exceptions are not thrown at Watir's level, but will be
thrown at RSpec level:
element.should exist # it doesn't yet due to some ajax

So i have to do:
wait_until {element.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.

Yes, you can, but you're still being forced to use those wait
invocations and put them somewhere manually, thus still having the
same problem in my mind. You're just hiding the problem at some other
level :P

>> 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.

But think about manual testing. No manual tester marks test as failing
because button appeared after 1 second due to some ajax request
because he/she waits it to appear. He/she doesn't even pay any extra
attention to it or think about "okay, i'm now waiting for the button
to appear". It is just a logical way to do. If the button doesn't
appear in a reasonable time then the test will be marked as a failed.
But when doing that thing automatically we have to write explicitly
"don't fail the test just yet, but try to be logical and wait for the
button to appear, please". Idea behind this would make tests more
natural by hiding these implicit waits away from the user level.
What's the real reason why you're against it? Currently you want more
to write because? You don't want to write types (even can't) of
variables in Ruby, but you'll have to do it in any statically written
language. That doesn't bother me in Ruby, does it bother you? If it
doesn't then why does it bother if the waiting is done somewhere in
lower level?

> 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).

Yep, but the not_exists?, not_visible? solution is also super simple
and you won't have to do it for every framework in use. Why not create
those methods into Watir itself then? Are we really afraid of adding 2
methods into API?

> or using the existing wait stuff
>  div.when_present.text.should == "expected text"

this doesn't work if the text itself is changed by JavaScript...

> 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.

Yes, agreed that the opposite case happens much rarer, but still happens.

>> 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.

Again, the value would be not to have to use wait_until everywhere.

>> 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.

Yup, but WebDriver doesn't work correctly if i'm waiting the opposite
case - !exists? - or does it?

>> 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.

Why is it more robust? As mentioned above it happens quite often where
wait_until is forgotten because test is passing when created, but will
start to fail later intermittently.

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

Again, i'm explicit - i want some element to exist and i don't care if
it exists right away or will exist after 2 seconds because that's what
i'd do with testing manually also.

> 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:
> Element#appears?
> Element#disappears?

Maybe having completely different method names is a good idea indeed,
but as mentioned below needs a custom RSpec matcher or element.should
be_appear... hehe.


In RSpec:
element.should have_appeared
element.should have_disappeared

Still not the best. Maybe there's some even better method name, which
would work with RSpec out-of-the-box.

> and some (custom) RSpec matchers:
> element.should appear
> element.should disappear
> Jari


More information about the Wtr-development mailing list