Selenium Wait in C#
At work we have been trying to get Selenium WebDriver working to help automate the testing of our Web Administration console. While on the surface Selenium seems like a great choice (lots of features, broad base of users, excellent support of web browsers), it can be a bit quirky from time to time.
One of the biggest problems we've had is getting the selenium wait states to work correctly. This article presents a method that can be used to get selenium to actually wait until page elements have loaded before performing a test action.
References:
- Selenium WebDriver [docs.seleniumhq.org]
- Explicit and Implicit Waits [docs.seleniumhq.org]
- Selenium c# Webdriver: Wait Until Element is Present [stackoverflow.com]
Background and Problem
The Selenium documentation states that this block of C# will cause selenium to wait until a page element is loaded before continuing:
IWebElement myDynamicElement = Wait.Until<IWebElement>((d) =>
{
return d.FindElement(By.Id("someDynamicElement"));
});
When we run this code it consistently throws exceptions when the element is not yet loaded. This was puzzling as the purpose of that code block is to WAIT until elements are loaded before continuing. Many people searched for a solution to this problem (beyond hard-coding Thread.Sleep(ms)) for awhile before I was asked to look into finding a solution. I googled and searched stack overflow to no avail.
Solution
After examining the Selenium documentation and looking at the exeptions that were being generated, I realized that things were not functioning as they were documented. Somewhere in the process there is an exception that isn't being handled and we need to handle it as a Selenium API consumer. Fortunately, the solution is very simple: Add a try/catch to the Lambda expression so we catch exceptions that don't matter (like the element not having loaded yet) and return null so the Selenium API knows to continue waiting until the element actually loads (null is what Wait.Until uses to know that a page element has not yet loaded). Here's my alteration to the above code:
WebDriverWait Wait = new WebDriverWait(WebDriver, TimeSpan.FromSeconds(30));
var FoundElement = Wait.Until<IWebElement>(d => {
try {
return d.FindElement(By.Id("someDynamicElement"));
} catch {
return null;
}
});
Remarks
It seems like there is always some quirk to be handled when using Selenium. After so many people put so much time into finding simple solutions for problems like the one described in this article I can see why organizations would pay big $$$ for a web automation solution which 'just works' and has vendor support. This isn't meant to knock Selenium: you get real value for your dollar if you can get Selenium to work for you. :)