Waiting
Properly synchronizing your code with the state of the browser has long been the biggest issue testers face when testing a dynamic website.
Sleeps
It is often discussed that hard coding #sleep
is a bad practice.
Besides being an indication that your test suite doesn’t have sufficient maturity, there are specific technical
frustrations that come with hard coding sleeps. The biggest issue is that you are having to balance the concern
of how long is long enough with having an additional and typically unnecessary set of 30 second sleeps
scattered everywhere throughout your code.
Selenium Waits - Implicit & Explicit
Selenium has two approaches to synchronization. The first is “implicit wait.” Presumably this feature was inspired by the early versions of Watir which did a better job of automatically waiting for elements. Using implicit waits means telling the driver to apply a global value for how long to wait when attempting to locate an element if it can’t find the element. The idea behind implicit waits is good, but there are two main issues with this form of implementation, so Watir does not recommend and does not provide direct access for setting them.
- The wait happens during the locate instead of when trying to act on the element. This makes it impossible to immediately query the state of an element before it is there.
- Implicit waits by themselves will not be sufficient to handle all of the synchronization issues in your code. The combination of delegating waiting responsibilities to the driver and leveraging polling in the code (explicit waits) can cause weirdness that is difficult to debug.
The second and recommended approach to waiting in Selenium is to use explicit waits. This retains responsibility for synchronization with your code. In this approach your code will continuously check to see if the supplied condition is met, and continue with the next piece of the code when so. Watir waiting approaches all leverage this idea of polling for the desired output from a supplied condition
When Present and When Enabled
Prior to Watir 6.0, the best way to ensure that the code waited for the browser to be ready was to insert a
#when_present
or #when_enabled
method before the action.
The problem here is that you should never be using #set
if you aren’t sure the element will be there or
enabled, so these #when_present
calls are philosophically redundant.
As such, Watir 6.0 deprecated #when_present
and #when_enabled
and every action call on an element
effectively executes this logic by default.
Note that Watir does its automatic waiting when taking actions, not when attempting to locate. This provides additional flexibility for querying the state of an element without needing unnecessary waits.
Watir Wait and Waitable Modules
Waitable
is the module that is included by Browser
, Alert
, Window
and Element
.
This module provides access to two main methods: #wait_until
and #wait_while
. As of Watir 6, both of these methods
accept :timeout
, :message
keyword parameters. Note that the :interval
keyword was added in Watir 6.1 to
allow reducing how often the condition is polled, and as of Watir 6.12 you can use a Proc
instance value for
:message
if that is preferred to a String
). Then as always, a block is passed in to establish what
condition needs to be met. #wait_until
will execute the block until a truthy result is returned, and
#wait_while
will execute the block until a falsy result is returned.
Note that it is encouraged to use #to_proc
syntax when possible:
The default timeout for Watir’s Waits is 30 seconds. You can pass in the :timeout
keyword parameter to
any of the wait methods, or you can change the global default with:
Wait Until Present and Wait While Present
As of 6.15 #wait_while_present
and #wait_until_present
are deprecated. For versions 6.2 through 6.14
these methods had subtly different behavior from .wait_until(&:present?)
& .wait_while(&:present?)
.
This is no longer the case and these methods should no longer be used.