I'm using Selenium with Python to test a web app; however, Firefox will periodically go in the "Not Responding" state. While Firefox is in this state the script will hang until I close it.
I tried:
br = webdriver.Firefox()
br.set_page_load_timeout(10)
and
br = webdriver.Firefox()
br.implicitly_wait(10)
I fear my issue won't be solved by a wait
or timeout
method since the page is Ajax. The .click()
or .submit()
method sends a POST
to answer a question and the response is a dictionary which via JavaScript updates the page with a new question. (This is what I understand from using the Network tab in Google Chrome Developer Tools Ctrl+Shift+I)
The question is:
How do I catch the Firefox Not Responding situation in Selenium?
I wish to catch this situation so I can close the browser and start a new one.
Edited after ExperimentsWithCode's answer:
Here is a snippet of my code to illustrate my problem.
def answer_questions(self):
q = QuestionParser(self.br.page_source)
q.add_to_db()
qid = q.get_qid()
# My answer
my_answer_id = q.get_my_answer()
self.br.find_element_by_id(my_answer_id).click()
# Submit answer
self.br.find_element_by_xpath('//*[contains(@id, "submit_btn_")]').click()
try:
find_id = "submit_btn_" + str(qid)
element = WebDriverWait(self.br,10).until(EC.presence_of_element_located((By.ID, find_id)))
except:
print 'I caught you'
self.rnd(mu=7, s=2) # a method to sleep for a random time
I call the answer_questions()
method in a loop. This code runs fine until Firefox crashes then it will hang until I close it. I read the docs and fear I've exhausted everything. The problem is not loading a page or element. The problem is that I don't know how to detect when Firefox crashes. WebDriverWait
seemed promising but it did not throw a TimeoutException
when Firefox crashed.
Thank you for your time.
I devised a remedy to my problem. Here is a snippet what I did:
import os, socket
from threading import Timer
def force_timeout(self):
os.system('taskkill /im firefox.exe /f /t')
# for Windows
# /im firefox.exe is to select firefox
# /f is to forcefully kill
# /t is to kill all child processes
for i in range(0, 1000):
try:
t = Timer(60, self.force_timeout)
# run force_timeout from new thread after 60 seconds
t.start() # start timer
self.answer_questions()
# if self.answer_questions() finishes before 60s, cancel timer
t.cancel() # cancel timer
except socket.error:
self.new_browser() # create a new browser
self.login() # login
self.go_to_questions() # Go to questions page so the loop can continue
# Code to recover from crash here
If the answer_questions()
method does not finish in 60 seconds the force_timeout()
will run from a new thread and forcefully kill firefox.exe
. Once Firefox is terminated the code will throw a socket.error
error. Catch this error then do what you need to do to recover from a browser crashing. I find the code to be a bit dirty but it's working exactly as i need it to.
For future reference: OS - Win8, Selenium Version - 2.40.0, Firefox Version - 27.0.1
Windows Taskkill
Python threading.Timer
How to open/launch firefox in selenium python. Open Mozilla Firefox browser and type in the address bar Firefox://version/ to check browser version to download the compatible version firefox Web driver as per Browser version. unzip and copy geckodriver.exe to the python script directory location.
Selenium IDE by SeleniumIt is implemented as a Firefox extension, and allows you to record, edit, and debug tests.
The Webdriver docs have a section on things like this here.
From the docs, you could try an Explicit Wait:
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
br = webdriver.Firefox()
br.get("http://somedomain/url_that_delays_loading")
try:
element = WebDriverWait(br, 10).until(EC.presence_of_element_located((By.ID, "_element_You_Are_Need_To_Load")))
finally:
br.quit()
This will time out if the element cannot be found in 10 seconds, or return the element within that window.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With