I want to control whether my WebDriver quit but I can't find a method for that. (It seems that in Java there's a way to do it)
from selenium import webdriver
driver = webdriver.Firefox()
driver.quit()
driver # <selenium.webdriver.firefox.webdriver.WebDriver object at 0x108424850>
driver is None # False
I also explored the attributes of WebDriver but I can't locate any specific method to get information on the driver status. Also checking the session id:
driver.session_id # u'7c171019-b24d-5a4d-84ef-9612856af71b'
If you would explore the source code of the python-selenium driver, you would see what the quit() method of the firefox driver is doing:
def quit(self):
"""Quits the driver and close every associated window."""
try:
RemoteWebDriver.quit(self)
except (http_client.BadStatusLine, socket.error):
# Happens if Firefox shutsdown before we've read the response from
# the socket.
pass
self.binary.kill()
try:
shutil.rmtree(self.profile.path)
if self.profile.tempfolder is not None:
shutil.rmtree(self.profile.tempfolder)
except Exception as e:
print(str(e))
There are things you can rely on here: checking for the profile.path to exist or checking the binary.process status. It could work, but you can also see that there are only "external calls" and there is nothing changing on the python-side that would help you indicate that quit() was called.
In other words, you need to make an external call to check the status:
>>> from selenium.webdriver.remote.command import Command
>>> driver.execute(Command.STATUS)
{u'status': 0, u'name': u'getStatus', u'value': {u'os': {u'version': u'unknown', u'arch': u'x86_64', u'name': u'Darwin'}, u'build': {u'time': u'unknown', u'version': u'unknown', u'revision': u'unknown'}}}
>>> driver.quit()
>>> driver.execute(Command.STATUS)
Traceback (most recent call last):
...
socket.error: [Errno 61] Connection refused
You can put it under the try/except and make a reusable function:
import httplib
import socket
from selenium.webdriver.remote.command import Command
def get_status(driver):
try:
driver.execute(Command.STATUS)
return "Alive"
except (socket.error, httplib.CannotSendRequest):
return "Dead"
Usage:
>>> driver = webdriver.Firefox()
>>> get_status(driver)
'Alive'
>>> driver.quit()
>>> get_status(driver)
'Dead'
Another approach would be to make your custom Firefox webdriver and set the session_id to None in quit():
class MyFirefox(webdriver.Firefox):
def quit(self):
webdriver.Firefox.quit(self)
self.session_id = None
Then, you can simply check the session_id value:
>>> driver = MyFirefox()
>>> print driver.session_id
u'69fe0923-0ba1-ee46-8293-2f849c932f43'
>>> driver.quit()
>>> print driver.session_id
None
I ran into the same problem and tried returning the title - this worked for me using chromedriver...
from selenium.common.exceptions import WebDriverException
try:
driver.title
print(True)
except WebDriverException:
print(False)
suggested methods above didn't work for me on selenium version 3.141.0
dir(driver.service) found a few useful options
driver.session_id
driver.service.process
driver.service.assert_process_still_running()
driver.service.assert_process_still_running
I found this SO question when I had a problem with closing an already closed driver, in my case a try catch around the driver.close() worked for my purposes.
try:
driver.close()
print("driver successfully closed.")
except Exception as e:
print("driver already closed.")
also:
import selenium
help(selenium)
to check selenium version number
This work for me:
from selenium import webdriver
driver = webdriver.Chrome()
print( driver.service.is_connectable()) # print True
driver.quit()
print( driver.service.is_connectable()) # print False
How about executing a driver command and checking for an exception:
import httplib, socket
try:
driver.quit()
except httplib.CannotSendRequest:
print "Driver did not terminate"
except socket.error:
print "Driver did not terminate"
else:
print "Driver terminated"
it works in java, checked on FF
((RemoteWebDriver)driver).getSessionId() == null
There is this function:
if driver.service.isconnectible():
print('Good to go')
In my case, I needed to detect whether the browser interface was closed - regardless - chromedriver's status. As such, none of the answers here worked, and I just decided to go for the obvious:
from selenium.common.exceptions import WebDriverException
try:
driver.current_url
print('Selenium is running')
except WebDriverException:
print('Selenium was closed')
Even though it's a bit of a hack, it's served my purposes perfectly.
''''python
def closedriver():
global drivername
drivername.quit()
global driveron
driveron=False
''''
this function "closedriver" uses a global variable named "drivername" and global bool variable named "driveron",you may just pass a current driver as parameter but
NOTE: driveron must be global to store the state of driver being 'on' or 'off'.
''''python
def closedriver(drivername):
global driveron
try:
drivername.quit()
except:
pass
driveron=False
''''
and when you start a new driver, just use a check
global driveron
if not driveron:
driver=webdriver.Chrome()
Related
I started learning python + selenium a few days ago, and am struggling to quit the browser outside of my bbdc_check function. My goal is whenever I interrupt bbdc_check or it encounters an error, I would like to quit the existing browser to start from scratch.
I keep encountering errors with quitting the browser. The error message for driver.quit() is "TypeError: quit() missing 1 required positional argument: 'self'".
I have a nagging suspicion that I'm supposed to use a class here, which I tried loosely off this solution, but still could not get it to work. Any ideas are appreciated, thank you.
FYI, date_a and date_b are not defined here because I deleted a bunch of code redundant to this issue. Assume that line of code works.
import selenium
from selenium import webdriver
import time
import sys
breakloop = 0
def bbdc_check():
global breakloop
driver = webdriver.Chrome(r'C:\<some dir>\chromedriver.exe')
driver.get('<a website>')
# A bunch of code here to compare 2 different dates
if (date_a < date_b):
breakloop = 1
else:
driver.quit()
time.sleep(600)
# The main while-loop to run the programme
while breakloop == 0:
try:
bbdc_check()
# If I manually interrupt, kill the programme
except KeyboardInterrupt:
driver = webdriver.Chrome
driver.quit()
sys.exit()
# If programme encounters error, try again from scratch
except:
driver = webdriver.Chrome
driver.quit()
time.sleep(30)
Seems you are creating new object of driver in each blocks as well as your function bbdc_check(). Create a single driver instance and use the same.
Debugging Selenium script with EventFiringWebDriver in PyCharm, cause exception to be logged:
'WebDriver' object has no attribute '__len__'
It slows down IDE but do not break (stop) the script.
Here is full code:
from selenium import webdriver
from selenium.webdriver.support.event_firing_webdriver import EventFiringWebDriver
from selenium.webdriver.support.events import AbstractEventListener
class ScreenshotListener(AbstractEventListener):
def on_exception(self, exception, driver):
print(exception)
driver = webdriver.Chrome('chromedriver.exe')
ef_driver = EventFiringWebDriver(driver, ScreenshotListener())
ef_driver.get('https://google.com/')
title = ef_driver.title
driver.quit()
assert "Google", title
When I run attached script in standard mode everything is OK.
But running with PyCharm Debug (here is output from beginning of Debug console):
C:\Pro\selenium-debug\venv\Scripts\python.exe "C:\Program Files\JetBrains\PyCharm Community Edition 2020.1.1\plugins\python-ce\helpers\pydev\pydevd.py" --multiproc --qt-support=auto --client 127.0.0.1 --port 59668 --file C:/Pro/selenium-debug/simple_test.py
I get those exceptions (every time when I call ef_driver):
'WebDriver' object has no attribute '__len__'
'WebDriver' object has no attribute '__len__'
It not stopping the script, it just cause debugger to be slow (it updates driver and focus is set to the browser).
Any idea why it is triggered and logged?
Bonus: Running debugging in console with pdb is OK, so this looks like strictly PyCharm Debug connected thing
Looks like PyCharm debug checks if an object has a __len__ attribute:
elif hasattr(v, "__len__")
and the object WebDriver has no __len__.
A solution could be (from the link below) to warp with try\catch:
try:
if is_numeric_container(type_qualifier, typeName, v):
xml_shape = ' shape="%s"' % make_valid_xml_value(str(v.shape))
elif hasattr(v, "__len__") and not is_string(v):
try:
xml_shape = ' shape="%s"' % make_valid_xml_value("%s" % str(len(v)))
except:
pass
except KeyError:
pass
Please check this track:
https://youtrack.jetbrains.com/issue/PY-39954
I am not able to solve the following issue :
Below is my python-selenium code.
import unittest
import time
import argparse, sys, os
import traceback
from selenium import webdriver
from selenium.common.exceptions import TimeoutException
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
class SeleniumTestPack(unittest.TestCase):
driver = webdriver.Firefox()
timeout = 30
def test_all(self):
admin_base_url = args.url
cognito_url = "test.auth.us-west-2.amazoncognito.com"
user_full_name = "test User"
email = "test#test.com"
firstName = "Selenium"
lastName = "User"
try:
self.test_redirect_to_congito_login_page(admin_base_url, cognito_url)
self.delete_geckodriver_log()
except Exception:
self.driver.save_screenshot('exception.png')
self.fail("Exception: %s" % (traceback.format_exc()))
def test_redirect_to_congito_login_page(self, admin_base_url, cognito_url):
print "Test navigating to home page redirects to cognito login page"
self.driver.get(admin_base_url)
self.wait_for_element_loaded(By.ID, "div-forms")
page_url = self.driver.current_url
assert cognito_url in page_url
def wait_for_element_loaded(self, id_type, id_locator):
min_timeout = 2
tries = 0
retry_limit = 13
while tries <= retry_limit:
try:
tries = tries + 1
element_present = EC.presence_of_element_located((id_type, id_locator))
WebDriverWait(self.driver, min_timeout).until(element_present)
break
except Exception:
if tries <= retry_limit:
continue
self.fail("Exception waiting for page to load %s : %s" % (id_locator,traceback.format_exc()))
def delete_geckodriver_log(self):
#running function at the end of all other invocation ensures all test cases have already ran successfully
geckodriverfile="geckodriver.log"
if os.path.isfile(geckodriverfile):
os.remove(geckodriverfile)
else:
print("Error: %s file not found" % geckodriverfile)
#classmethod
def tearDown(self):
# close the browser window
self.driver.quit()
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='test')
parser.add_argument('--url',action='store',dest='url',default=None,help='<Required> url link',required=True)
parser.add_argument('--username',action='store',dest='username',default=None,help='<Required> username',required=True)
parser.add_argument('--password',action='store',dest='password',default=None,help='<Required> password',required=True)
parser.add_argument('unittest_args', nargs='*')
args = parser.parse_args()
sys.argv[1:] = args.unittest_args
unittest.main()
I am running this test using below command.
xvfb-run --server-args="-screen 0, 1280x1024x8" python admin-ui-test.py --url 'http://localhost:8080' --username 'test' --password 'test1234'
Below is my output:
ERROR: test_redirect_to_congito_login_page (__main__.SeleniumTestPack) TypeError: test_redirect_to_congito_login_page() takes exactly 3 arguments (1 given)
Anything wrong i am doing? I have similar kind of tests at other places as well, Which are working fine since long time.
Any help will be highly appreciated.
The solution is very much new to me.
The function name should not start with "test_" (Otherwise it will be consider as a separate Test Case)
I renamed the function name and it is working fine!
I am facing a problem automating the protection settings in IE using Selenium with python.
I found a solution to automate the settings in java but it is not working when i changed it to python .
I tried the following::
from selenium import webdriver
caps=webdriver.DesiredCapabilites.INTERNETEXPLORER
caps['INTRODUCE_FLAKINESS_BY_IGNORING_SECURITY_DOMAINS']=True
driver=webdriver.Ie(caps)
This gave an error with respect to the argument given .
and when I used driver = webdriver.Ie()
It says protection mode settings must be same for all zones.
Can anyone help me automate this thing using selenium in python.
According to documentation, in python-selenum, you should use setting called
ignoreProtectedModeSettings:
from selenium import webdriver
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
caps = DesiredCapabilities.INTERNETEXPLORER
caps['ignoreProtectedModeSettings'] = True
driver = webdriver.Ie(capabilities=caps)
Desired capabilities doesn't work in some instances. Here is a method to change protection settings from the registry using winreg.
from winreg import *
def Enable_Protected_Mode():
# SECURITY ZONES ARE AS FOLLOWS:
# 0 is the Local Machine zone
# 1 is the Intranet zone
# 2 is the Trusted Sites zone
# 3 is the Internet zone
# 4 is the Restricted Sites zone
# CHANGING THE SUBKEY VALUE "2500" TO DWORD 0 ENABLES PROTECTED MODE FOR THAT ZONE.
# IN THE CODE BELOW THAT VALUE IS WITHIN THE "SetValueEx" FUNCTION AT THE END AFTER "REG_DWORD".
#os.system("taskkill /F /IM iexplore.exe")
try:
keyVal = r'Software\Microsoft\Windows\CurrentVersion\Internet Settings\Zones\1'
key = OpenKey(HKEY_CURRENT_USER, keyVal, 0, KEY_ALL_ACCESS)
SetValueEx(key, "2500", 0, REG_DWORD, 0)
print("enabled protected mode")
except Exception:
print("failed to enable protected mode")
In case capabilities mode does not work, there is an alternative.
from selenium import webdriver
from selenium.webdriver.ie.options import Options
ie_options = Options()
ie_options.ignore_protected_mode_settings = True
driver = webdriver.Ie(options=ie_options)
driver.get('http://www.google.com')
Here is another variation on Dinesh's code that works to disable protected modes in the registry. It also closes the connection.
Simply put this code before your selenium automation code, and it will prepare the browser.
import winreg
def set_reg(REG_PATH, name, value):
try:
winreg.CreateKey(winreg.HKEY_CURRENT_USER, REG_PATH)
with winreg.OpenKey(winreg.HKEY_CURRENT_USER, REG_PATH, 0, winreg.KEY_WRITE) as registry_key:
winreg.SetValueEx(registry_key, name, 0, winreg.REG_DWORD, value)
winreg.CloseKey(registry_key)
return True
except WindowsError:
return False
for i in range(1,5): set_reg(r"Software\Microsoft\Windows\CurrentVersion\Internet Settings\Zones\\" + str(i),'2500', 3)
Adapted from the top answer in this thread by Mash and icc97:
python script to read and write a path to registry
I am executing selenium test cases via Proboscis, for good reporting of test results. I have the following test case written
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from proboscis import test
import unittest
driver = webdriver.Firefox()
#test(groups=["unit","login"])
class UI_test(unittest.TestCase):
def test_SuccessfulErrorMsgOnEmptyUserName(self):
driver.get("http://127.0.0.1:7999/login/")
username_input = driver.find_element_by_id("id_email")
username_input.send_keys('')
password_input = driver.find_element_by_id("id_password")
password_input.send_keys('bill3')
driver.find_element_by_xpath('//input[#value = "Log In"]').click()
driver.implicitly_wait(3)
driver.find_element_by_class_name("error-login")
driver.close()
def run_tests():
from proboscis import TestProgram
# from tests import unit
# Run Proboscis and exit.
TestProgram().run_and_exit()
if __name__ == '__main__':
run_tests()
What could be causing the BadStatusLine exception in this code?
Looks like a duplicate of Python/Django "BadStatusLine" error but i can't flag due to this question having a bounty. According to this answer, a BadStatusLine exception is likely caused by an empty response, as in there being no status line at all.
According to this answer, the server formally tells the client there is no more data, instead of simply causing a connection reset or rude timeout.