5

Oftentimes, to tackle timing issues and to keep end-to-end tests powered by Selenium more reliable, we add explicit waits to the testing flow. Sometimes, after an explicit wait there is an assertion that basically checks what we were waiting for with an Explicit Wait.

Examples in Python:

WebDriverWait(driver, 10).until(EC.title_is("Page Title"))
self.assertEqual(driver.title, "Page Title")

element = WebDriverWait(driver, 10).until(EC.visibility_of_element_located((By.ID, "myId")))
self.assertTrue(element.isDisplayed())

On one hand these assertions duplicate wait condition checks. On the other, assertions are more explicit and readable.

How do you deal with this kind of situations? What would we lose if we remove the assertions leaving only explicit waits?

2 Answers 2

4

You have two lines of code of which the second is fully redundant (because the first already does the same, and more).

I do agree that defining a new WebdriverWait every time isn't very readable too.

Thus, the solution could be simple:

  • define a WebdriverWait one time at framework level (static if need be)
  • create a helper method that uses this variable

In my C# framework, for example, I can simply use Browser.WaitFor(condition);

Furthermore, if you read my response in another of your questions, you will notice the phrase

I never have to add a wait or a clear() in my PageObjects again (when dealing with individual elements)

Because when using framework wrapper methods for WebElement actions, you can put in them what you want - even assertions per your question (see my example below). The main advantage is highly reduced and very clean code in Page Objects and consistency across Page Objects in dealing with elements. High-level example for entering text with C# extension methods (but in other languages you will probably find different syntax to achieve the same).

PageObject

When using PageFactory to initialize the elements, my only line of code would be this (even though the field is not necessarily loaded at this point)

username.SetText("user");

Framework

All the waiting and additional actions (clearing the element first) are done behind the scenes. The waiting works because of using PageFactory and catching the NoSuchElementException in the framework (with a WebDriverWait).

public void SetText(this IWebElement element, string text)
{
  // first, wait until element is visible using another extension method
  // in this method a WebDriverWait is used, so it only returns once found
  element.ShouldBeVisible();
  // if you want to, assert visibility again
  // it's only defined once here in the framework so your Page Objects stays clean
  Assert.IsTrue(element.Displayed);
  // then enter text
  element.Clear();
  element.SendKeys();
}
4

I have combined advantages of both into a single command:

waitThat(element.getText(), equalTo("Something"), noLongerThan(min(1)), checkEvery(sec(1)));

That's Java but I am sure you can build a similar thing in Python.

2
  • You can combine them, but did it make code more, or less readable? I know that Java programmers are used to parse complicated statements all the time. Something similar would be considered non-pythonic, because one of the zen rules of Python says "Readability counts". Commented Jul 31, 2017 at 13:52
  • @PeterMasiar. I and other team mates find it quite readable because it has syntax similar to popular Java APIs: assertThat fron Hamcrest and waitUntil from Awaitility.
    – dzieciou
    Commented Jul 31, 2017 at 17:48

Not the answer you're looking for? Browse other questions tagged or ask your own question.