Revamp Selenium: The power of explicit waits

Revamp Selenium (2 Part Series)

1 Revamp Selenium: Refine the way you use parent-child selectors
2 Revamp Selenium: The power of explicit waits

Working and testing with selenium will make us very patient developers. We fill our code with a lot of waits all the time, and is natural and is expected.

UI tests have a huge dependency on the external conditions of the system under tests, for example: rendering speed, internet connection and third party tools. Also sometimes we need to wait because it is how our system behaves and we need certain conditions to be full-filled before our test can continue executing.

Selenium provides 2 ways of waiting (+1 non selenium):

  • Implicit wait: Just gives the driver a range of time to find an element before breaking the execution. In natural words: Hey selenium if you can’t find my elements in 30 seconds please finish the test.
  • Explicit wait: Verifies for conditions of an element to be full-filled before breaking or continue with the execution. Hey selenium, find my element but also make sure it has as a class before continue.
  • Sleep: We sleep our execution thread, then proceed. Hey selenium STOP . . . . . . . . please proceed.

Talking about explicit waits

Imagine we are working with a countdown website, and we want to make sure that the counter actually works.

driver = webdriver.Chrome(DRIVER_LOCATION) #driver driver.get("https://gcalvocr.github.io/countdown-app/")

print('**** Click on 1 Minute ****')
driver.find_element_by_id("btn-1").click() # click on start 1 minute countdown 

Enter fullscreen mode Exit fullscreen mode

At this point we could be tempted to add a 60 seconds hardcoded wait and they verify that the counter is 00:00.

time.sleep(60000)
if driver.find_element_by_id('countdown').text == '00:00':
  print('Yes, the counter worked')
else:
  print('Nop, The expected value is not correct')

Enter fullscreen mode Exit fullscreen mode

And the solution works as a charm.
.

But, what if it fails? We would have to wait 1 entire minute to figure it out. What if our element is not visible anymore after 2 seconds? What if the counter never started?

Let’s create a custom explicit wait

class element_has_text(object):
  def __init__(self, locator, text): #python contructor     self.locator = locator
    self.text = text

  def __call__(self, driver):
    element = driver.find_element(*self.locator) # find the element     if element.text == self.text: # if the element text is expected return true         return True
    else:
        return False

Enter fullscreen mode Exit fullscreen mode

The code above extends the WebDriverWait class to add a new custom wait. This custom wait is going to verify constantly for the condition if element.text == self.text, but will break the test only when the given time is burned down and the condition was not met.

So the new code could look like this using the WebDriverWait and the custom element_has_text.

  print('**** Click on 1 Minute ****')
  driver.find_element_by_id("btn-1").click() # click on start 1 minute countdown 
wait = WebDriverWait(driver, 10) # wait max 10 seconds locator = (By.ID, 'countdown') # element locator wait.until(element_has_text(locator, '00:55'))
print('**** Timer has 55 seconds left ****')
wait.until(element_has_text(locator, '00:45'))
print('**** Timer has 45 seconds left ****')
wait.until(element_has_text(locator, '00:35'))
print('**** Timer has 35 seconds left ****')
# this will break now wait.until(element_has_text(locator, '00:10'))

Enter fullscreen mode Exit fullscreen mode

And the outcome is a sweet selenium.common.exceptions.TimeoutException that we can handle as part of the test failure:

This is quite more powerful, because it is also looking for the element and verifying a property. In case the element can’t be found the test will also break.

Final thoughts

Selenium has several built in explicit waits that will adapt to most of the use cases, so there might no be need for you to create a custom one. But I wanted to go a step further and demonstrate that you can easily extend your testing framework and adapt to your system under test.

Note: I don’t want to say that sleep.wait() is the devil and that you should try to avoid it, but yes it is the devil and you should avoid it as much as possible.

Please take your time to read the selenium documentation and reach out if you need any advice on how to improve your code quality and tests speed.

Waits

Comments?

cheers 🙂 and remember to keep waiting
https://pjcalvo.github.com

if you liked the post:

Revamp Selenium (2 Part Series)

1 Revamp Selenium: Refine the way you use parent-child selectors
2 Revamp Selenium: The power of explicit waits

原文链接:Revamp Selenium: The power of explicit waits

© 版权声明
THE END
喜欢就支持一下吧
点赞12 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容