Reputation: 2126
so I'm reasonably new to Robot Framework and have run into various forms of this issue a number of times now. Essentially I create a suite of tests which eventually pass and check for the things I expect, they then go through a CI/CD pipeline and on the dedicated test runners I hit some failures. In essence this seems to be because the test runners do things a little faster, whether due to hardware or selenium speed, it doesn't really matter.
To avoid these failures I end up adding to the tests to 'slow' them down at certain points to ensure success, basically bloating them or just being a little more protective. So for those with more experience, how do you handle this situation? I'd like to stick with best practice as far as I can, i.e. I'm not just using sleeps everywhere but using implicit waits, still I don't know what the best approaches are.
Here's snippet of an issue I've hit recently:
Wait Until Page Contains Element ${STATIC_TABLE_XPATH}/somepath 10
${image_text} = Selenium2Library.Get Element Attribute ${STATIC_TABLE_XPATH}/somepath
${second_paragraph_text} = Selenium2Library.Get Text ${STATIC_TABLE_XPATH}/somepath
So basically despite these being functionally correct, they pull back nothing sometimes when run on the test runners. I figure this is because things are happening too quickly, so I added a Wait Until Page Contains Element, unfortunately the same problem still exists. Is there a best way to handle this situation so it consistently passes?
I thought adding a wait until keyword succeeds on the expected variable value would be pretty horrible but happy to be proved wrong!
Upvotes: 0
Views: 6125
Reputation: 2280
Even though you feel it's horrible, I think the best way to slow Selenium down is to keep polling element attribute until you get a proper variable. There is no harm in trying to something until it succeeds. If you have a bug, attribute value will never be ok. I believe Wait Until Keyword Succeeds keyword was made just for cases like this. I use it all the time.
Upvotes: 1
Reputation: 25714
drkthng's reasoning is correct but you don't need to write all that code... it already exists in ExpectedConditions
. A simple example
WebDriverWait wait = new WebDriverWait(driver, 10);
wait.until(ExpectedConditions.presenceOfElementLocated(locator));
Take a look at the docs for all the available methods (there are a bunch) and how to use them.
Upvotes: 2
Reputation: 6939
Avoid Sleep as much as you can.
Implicit waits are also not a solution that scales. They can hold you back big time if you are checking the "non-existence" of elements for example.
I would suggest you make good use of WebDriverWaits.
I often have to wait for certain elements or pages to display, so I wrote some methods like this:
public void waitUntilDisplayed(By elementLocator, int timeoutInSeconds) {
WebDriverWait wait = (WebDriverWait)new WebDriverWait(driver, timeoutInSeconds).ignoring(StaleElementReferenceException.class);
wait.until(new ExpectedCondition<Boolean>() {
public Boolean apply(WebDriver driver) {
return elementIsDisplayed(elementLocator);
}
});
}
public boolean elementIsDisplayed(By elementLocator) {
if(elementExists(elementLocator)) {
WebElement element = driver.findElement(elementLocator);
return element.isDisplayed();
}
return false;
}
public boolean elementExists(By elementLocator) {
List<WebElement> elements = driver.findElements(elementLocator);
if (elements.size() < 1) {
return false;
}
return true;
}
Upvotes: 0