4

I am using the python unit testing library (unittest) with selenium webdriver. I am trying to find an element by it's name. About half of the time, the tests throw a NoSuchElementException and the other time it does not throw the exception.

I was wondering if it had to do with the selenium webdriver not waiting long enough for the page to load.

Gengar
  • 123
  • 2
  • 8

7 Answers7

12
driver = webdriver.WhatEverBrowser()
driver.implicitly_wait(60) # This line will cause it to search for 60 seconds

it only needs to be inserted in your code once ( i usually do it right after creating webdriver object)

for example if your page for some reason takes 30 seconds to load ( buy a new server), and the element is one of the last things to show up on the page, it pretty much just keeps checking over and over and over again if the element is there for 60 seconds, THEN if it doesnt find it, it throws the exception.

also make sure your scope is correct, ie: if you are focused on a frame, and the element you are looking for is NOT in that frame, it will NOT find it.

TehTris
  • 3,139
  • 1
  • 21
  • 33
  • pretty cool I never knew you could do that, also good point about frames, that has tripped me up before – qwwqwwq May 24 '13 at 16:58
  • it has literally tripped up every webriver user ever in the history of selenium. I used to write entire defs like @Akkabar's answer for this and then stumbled upon it one day like "wow these guys already thought of that" – TehTris May 24 '13 at 17:02
  • 4
    `driver.get()` is a blocking operation; the webdriver browser plugins don't respond to the calling client (bindings in your language of choice) until the driver has determined that the page has loaded completely, basically when all GETs have returned and the DOM is completed. However, if you have asynchronous content (JS that modifies the DOM after the initial page load is complete, etc), you will likely need to wait on an element, as it won't be in the initial completed DOM. Setting a global implicit wait is a quick fix, but it can have negative impact if test runtime matters to you. – Silas Ray May 24 '13 at 17:49
  • i agree @sr2222 , especially if you use try statements. – TehTris May 24 '13 at 18:46
5

I see that too. What I do is just wait it out...

you could try:

while True:
    try:
        x = driver.find_by_name('some_name')
        break
    except NoSuchElementException:
        time.sleep(1)
        # possibly use driver.get() again if needed

Also, try updating your selenium to the newest version with pip install --update selenium

eran
  • 14,496
  • 34
  • 98
  • 144
3

I put my money on frame as I had similar issue before :)

Check your html again and check if you are dealing with frame. If it is then switching to correct frame will be able to locate the element.

Python

driver.switch_to_frame("frameName")

Then search for element.

If not, try put wait time as others suggested.

user2388556
  • 287
  • 1
  • 7
  • 17
1

One way to handle waiting for an element to appear is like this:

import selenium.webdriver.support.ui as ui
wait = ui.WebDriverWait(driver,10)
wait.until(lambda driver: driver.find_by_name('some_name') )
elem = driver.find_by_name('some_name')

You are correct that the webdriver is not waiting for the page to load, there is no built-in default wait for driver.get().

qwwqwwq
  • 6,999
  • 2
  • 26
  • 49
0

To resolve this query you have to define explicit wait. so that till the time when page is loading it will not search any WebElement. below url help on this. http://docs.seleniumhq.org/docs/04_webdriver_advanced.jsp

0

You need to have a waitUntil (your element loads). If you are sure that your element will eventually appear on the page, this will ensure that what ever validations will only occur after your expected element is loaded.

Kermit_ice_tea
  • 508
  • 2
  • 8
  • 16
0

I feel it might be synchronisation issue (i.e webdriver speed and application speed is mismatch )

Use Implicit wait:

driver.manage.timeouts.implicitlyWait(9000  TIMEUNITS.miliseconds)

Reference

michaldo
  • 4,195
  • 1
  • 39
  • 65