WebDriver Waiting Practices
In Cycle 2.22, Cycle Labs released the WebDriver step plugin, which provided new implementations for all web steps with cleaner code that ran more efficiently. The plugin also improved the steps’ internal waiting mechanisms so that their interactions would be inherently more reliable without needing extra CycleScript code. As a result, CycleScript code in our libraries and projects for WebDriver steps can be improved. This article explains how waiting works for WebDriver steps and how to write CycleScript code with better practices.
How waiting works
Every web step performs an interaction on a page rendered in a web browser using Selenium WebDriver. However, to be reliable, each interaction needs to wait for its “target” to be “ready” before firing. For example, if a step intends to click a button, then the button must both be displayed on the page and be enabled before the step can send the click action. Otherwise, the click will not find the button, and Selenium will raise an error. Improper waiting is the bane of black box test automation because it inevitably causes intermittent failures.
The target and the readiness condition for each step is different, but they follow common sense:
-
Steps that interact with elements wait for the element to be displayed.
-
Steps that interact with alerts wait for the alerts to appear.
-
Steps that perform verifications wait for the verification condition to become true.
Almost all WebDriver steps perform some kind of waiting. Only a few steps do not have a target (such as “I refresh web browser”) and therefore do not perform internal waiting.
Furthermore, all automatic waiting happens before the interaction is performed. A step does not add waiting after the interaction is performed to verify that it was successful. Instead, follow-up steps must verify any outcomes. For example, if a test clicks a button to open a popup window, the click step does not wait after firing the click for the popup to appear; a separate step must check the popup. The pattern of waiting automatically before and not after interactions ensures that steps wait only where necessary, which keeps tests more efficient overall.
Every wait must have a timeout: an amount of time that the automation will continuously check for the target to be ready until it stops and yields an error. Timeouts ensure that tests do not get stuck in infinite loops waiting for conditions that will never happen. Web steps can set local timeouts with the suffix “within X seconds” or via a global timeout configured in execution settings that is applied to all steps. Explicit local timeouts override the global timeout.
Avoiding anti-patterns
Many scenarios in the libraries and in customer/partner projects add extra CycleScript code for waiting that is no longer required with the new WebDriver plugin. This code was often written with good intentions to perform interactions safely but now is no longer necessary – and is even detrimental. Extra code makes tests harder to maintain, slower to execute, and more confusing to troubleshoot.
Double waiting
- The “Once” keyword, which handles it at the level of the language
- The “within 5 seconds” suffix, which handles it at the level of the step
Timeout variable configurations
The automatic waiting in the click step is a “smart” wait in that it will repeatedly check if the button becomes ready during the timeout period. So, if the button becomes ready after only 2 seconds, the step will identify that it is ready, stop waiting, and fire the click. The 10 seconds specified in the suffix represents the maximum amount of time the step will wait, not the minimum amount of time the step must take.
Hard waits are one of the worst anti-patterns in black box test automation because they force tests to take much more time than necessary. They also do not guarantee that the target for the step is actually ready to receive interaction. Instead, a hard wait just presumes that the system will make the target ready within the given waiting time. Therefore, hard waits should be avoided as much as possible.
Applying Better Practices
Please keep these practices in mind when writing CycleScript code. Note that they are applicable only for WebDriver steps. Other kinds of steps might still need explicit safety checks or the “Once” keyword.