Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Handle Firefox Not Responding While Using Selenium WebDriver With Python?

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

like image 420
Delicious Avatar asked Mar 12 '14 03:03

Delicious


People also ask

How do I run Firefox in Selenium Python?

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.

Does Selenium work with Firefox?

Selenium IDE by SeleniumIt is implemented as a Firefox extension, and allows you to record, edit, and debug tests.


1 Answers

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.

like image 169
ExperimentsWithCode Avatar answered Oct 20 '22 15:10

ExperimentsWithCode