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