Selenium webdriver can drive different browsers like as Firefox, Chrome or Internet Explorer. These browsers actually cover the majority of internet users, so testing these browsers possibly covers the 90% of the internet users. However, there is no guaranty that the same automation scripts can work without a failure on these three browsers. For this reason, automation code should be error-prone for the browsers you want to cover.
The following error is caught when the test script run for Chrome and Internet Explorer, but surprisingly there is no error for the Firefox. Selenium gives an error like below:
Traceback (most recent call last):File "D:\workspace\sample_project\sample_run.py", line 10, in <module>
m.login()
File "D:\workspace\sample_project\test_case_imps.py", line 335, in login
driver.find_element_by_id("id_username").clear()
File "C:\Python27\lib\site-packages\selenium-2.35.0-py2.7.egg\selenium\webdriver\remote\webelement.py", line 62, in clear
self._execute(Command.CLEAR_ELEMENT)
File "C:\Python27\lib\site-packages\selenium-2.35.0-py2.7.egg\selenium\webdriver\remote\webelement.py", line 228, in _execute
return self._parent.execute(command, params)
File "C:\Python27\lib\site-packages\selenium-2.35.0-py2.7.egg\selenium\webdriver\remote\webdriver.py", line 165, in execute
self.error_handler.check_response(response)
File "C:\Python27\lib\site-packages\selenium-2.35.0-py2.7.egg\selenium\webdriver\remote\errorhandler.py", line 164, in check_response
raise exception_class(message, screen, stacktrace)
selenium.common.exceptions.InvalidElementStateException: Message: u'invalid element state: Element is not currently interactable and may not be manipulated\n (Session info: chrome=29.0.1547.76)\n (Driver info: chromedriver=2.3,platform=Windows NT 6.2 x86_64)'
In this example, while Firefox can find the element, however Chrome and Internet Explorer can't find the element. This is because the Firefox can load the page little bit faster than the other, and when the other browsers look up the element, it not loaded yet. To solve the problem we can let the browser wait until the browsers can load the element. time.sleep(1) adds the following piece of code wait for 1 second before executing the line 335. Similarly, driver.implicitly_wait(1) can be used.
from selenium import webdriver from selenium.webdriver.common.by import By driver = webdriver.Firefox() driver.find_element_by_css_selector("span.ml5.dib").click() time.sleep(1) driver.find_element_by_id("id_username").clear() driver.find_element_by_id("id_username").send_keys("tst@test.com")
A better approach is to wait until a dynamic object in the opening page is visible which means that the page is loaded correctly. Then we can click the object. The loading time can be different because of the browser and the connection speed. Therefore this approach can solve other possibilities. You can use WebDriverWait, to use this you must import this library first as in the example.
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait # available since 2.4.0
from selenium.webdriver.support import expected_conditions as EC # available since 2.26.0
driver = webdriver.Firefox()
driver.find_element_by_css_selector("span.ml5.dib").click()
# wait until a dynamic object to be visible
# for as much as timeout, as 10 second here
try:
element = WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.ID, "myDynamicElement")))
finally:
driver.quit()
driver.find_element_by_id("id_username").clear()
driver.find_element_by_id("id_username").send_keys("tst@test.com")