zb226
zb226

Reputation: 10500

Selenium: Explicit / Unconditional wait, i.e. "just wait"

As it turns out, the WebDriverWait class does not allow for an "unconditional wait": you always have to specify a certain condition to wait for. However, for example when setting up a project and developing first tests, waiting unconditionally is a helpful feature. The usage of Thread.sleep() is often discouraged. Are there better solutions for the "just wait"-problem?

I'm using the latest Selenium/WebDriver release as of now - 2.44.0.

Upvotes: 1

Views: 2608

Answers (3)

Ondra Žižka
Ondra Žižka

Reputation: 46796

If you want to stay Selenium-integral, you may use:

Sleeper.SYSTEM_SLEEPER.sleep(Duration.ofSeconds(3))

I can see a use case for that when you want to slow down the things a bit to see what is happening in the browser. So I make it conditional:

Sleeper.SYSTEM_SLEEPER.sleep(Duration.ofMillis(slowDownFactor * 100))

slowDownFactor 0 by default, or more when in a development profile (in my case, a Spring profile, through:

@Value("${debug.slowDownFactor:0}") private int slowDownFactor;

Upvotes: 0

Louis
Louis

Reputation: 151380

Qwerty's answer is correct insofar as the principle is, to paraphrase:

Do not "just wait" if you can actually wait for something significant to happen in the browser. In other words, you be waiting for a specific event rather than "just waiting".

Ok, but let's assume, for the sake of argument, that you're in a situation where there is absolutely positively no event you can wait for. I have large test suites that use Selenium and I've never been in this situation, but I'm not omniscient. There could be situations I'm not foreseeing. It is possible that Thread.sleep() is going to give you want you want, however:

  1. If you are running your browser on a remote provisioning service like Sauce Labs or Browser Stack, they may decide that your script is dead and shut down the browser. (Sauce Labs definitely does this. I've never used Browser Stack but I would expect the same.)

  2. If a network issue happens while you are waiting and it is such as to cause a test failure, you won't know it until you Thread.sleep() call is done. This, again, can happen if you use services like those I've mentioned above. It happens to my test suites once in a while.

  3. Or if you are testing locally: the browser crashes or enters an infinite loop. I've not experienced crashes but I've experienced infinite loops. Again, if you use Thread.sleep() you won't know about the issue until you are done waiting.

Of course, the longer you want to wait, the more of an issue it is. If you just want to wait for a second... then you should be fine with Thread.sleep(). Otherwise, if I were backed against the wall and had to "just wait" I'd still use Selenium's waiting facilities, I'd do something like:

try: 
    WebDriverWait(driver, timeout).until(
        lambda driver: driver.execute_script("return false"))
except TimeoutException:
    pass # Do nothing

This is Python code but the principle is the same in any language that Selenium supports: just wait for something that cannot ever occur. It is important that the wait executes a test that happens on the browser side because the whole point of doing this instead of using something like Thread.sleep() is so that the browser is contacted and we find issues as early as possible. The way WebDriverWait works, it will poll the browser every so often (every 0.5 seconds is the default in the Python implementation). The test could be a find_element method that searches for an element that cannot exist. I've used an execute_script that returns false. Since it is never going to return a true value, the wait will timeout. (Executing an empty script would also work, as it would return undefined which translates to a falsy value but return false looks deliberate whereas an empty script looks like a mistake.) Then you just need to ignore the exception raised due to timing out. If you do this often you can even wrap the whole thing in a utility function.

Upvotes: 2

Qwerty
Qwerty

Reputation: 31919

If you just need to wait, then Sleep is fine.

The point of not using Sleep is not in the sleep itself, but in the just waiting as you described it. Just waiting is what you should not. Try changing your thinking, find some event you can attach the wait to. Make it conditional.

In web testing, you don't usually need to just wait. You wait until page loads, until animation finishes, until form sends, element is clickable, user logs in, script executes, data are processed... That's why Sleep is discouraged, but if you really don't have a single event you are waiting for and simply need to just wait, then using the Sleep is perfectly OK.

Upvotes: 4

Related Questions