Check if the browser opened with Selenium is still running (Python) - python

I want to check if a browser opened with Selenium is still open. I would need this check for closing a program. If the browser is not open, then the GUI should be destroyed without a message (tk.messagebox) coming. But if the browser is open, then the message should come as soon as the function is activated. Here is the function:
def close():
msg_box = tk.messagebox.askquestion('Exit Application', 'Are you sure you want to exit the application?',
icon='warning')
if msg_box == 'yes':
root.destroy()
try:
web.close()
except NameError:
sys.exit(1)
except InvalidSessionIdException:
sys.exit(1)
except WebDriverException:
sys.exit(1)
else:
return

I don't think there is a direct api for checking browser status. But you can use the the work around
def isBrowserAlive(driver):
try:
driver.current_url
# or driver.title
return True
except:
return False

Unfortunately, there's not a standardized way to check a driver's status.
Here's the most reliable cross-browser workaround that I've come up with over the years:
from selenium.common.exceptions import NoSuchElementException
from selenium.common.exceptions import WebDriverException
def is_webdriver_alive(driver):
print('Checking whether the driver is alive')
try:
assert(driver.service.process.poll() == None) #Returns an int if dead and None if alive
driver.service.assert_process_still_running() #Throws a WebDriverException if dead
driver.find_element_by_tag_name('html') #Throws a NoSuchElementException if dead
print('The driver appears to be alive')
return True
except (NoSuchElementException, WebDriverException, AssertionError):
print('The driver appears to be dead')
return False
except Exception as ex:
print('Encountered an unexpected exception type ({}) while checking the driver status'.format(type(ex)))
return False
Usage:
driver_is_alive = is_webdriver_alive(driver)

Related

Open 2 Webdrivers at same time with multi-threading

I am working on Crawl project using Selenium and Webdriver. Since that data I need to crawl while big, I want to split it to 2 threads and run at the same time. But when I start 2 Webdrivers at the same time, my code can not recognize which driver belong to which thread to fill the information.
This is the code that I setup 2 threads run main function:
if __name__ == '__main__':
data = load_data(INPUT_DIR)
t1_data = data[:250]
t2_data = data[250:]
try:
_thread.start_new_thread(main, (t1_data, LOG_FILE_T1))
_thread.start_new_thread(main, (t2_data, LOG_FILE_T2))
except:
print ("Error: unable to start thread")
while 1:
pass
This code I start the Webdriver:
def start_driver():
global driver
options = Options()
options.add_argument("--disable-notification")
options.add_argument("--disable-infobars")
options.add_argument("--mute-audio")
#options.add_argument("headless")
driver = webdriver.Chrome(options=options)
Two Webdrivers after started, I will fill in the username/password
information on facebook.com
def login(email, password):
""" Logging into our own profile """
try:
driver.get('https://mbasic.facebook.com')
time.sleep(DELAY_TIME)
driver.find_element_by_name('email').send_keys(email)
driver.find_element_by_name('pass').send_keys(password)
driver.find_element_by_name('login').click()
# deal with "Not Now" button if it show off at first time
not_now_button = driver.find_element_by_xpath("//a")
if not_now_button.size != 0:
not_now_button.click()
except Exception as e:
print('Error in Login')
print(e)
exit()
At send_keys step, both threads fill in the same text box in 1 Webdriver.
How can I change my code for 2 threads can see different Webdrive and fill the info in ?
Just found out the solution, I want to share here if someone needed.
Instead of global driver, I will change to a local driver and pass it to each function.
def start_driver():
options = Options()
options.add_argument("--disable-notification")
options.add_argument("--disable-infobars")
options.add_argument("--mute-audio")
#options.add_argument("headless")
driver = webdriver.Chrome(options=options)
return driver
def login(driver, email, password):
""" Logging into our own profile """
try:
driver.get('https://mbasic.facebook.com')
time.sleep(DELAY_TIME)
driver.find_element_by_name('email').send_keys(email)
driver.find_element_by_name('pass').send_keys(password)
driver.find_element_by_name('login').click()
# deal with "Not Now" button if it show off at first time
not_now_button = driver.find_element_by_xpath("//a")
if not_now_button.size != 0:
not_now_button.click()
except Exception as e:
print('Error in Login')
print(e)
exit()
By this, 2 threads can see different Webdriver and fill their own information.

Selenium Alert Handling Python

So I am using Selenium to simply go to a given list of websites and take a screenshot of them. However I have run into some having alerts and some do not. I am looking to do something along the lines of if alert then this else keep moving.
Here is my current code
from selenium import webdriver
import pandas as pd
import time
path = "C:/Users/dge/Desktop/Database/NewPythonProject/html Grabber/Output/Pics/"
df = pd.DataFrame()
df = df.append(pd.read_csv('crime.csv'), ignore_index=True)
driver = webdriver.Chrome('C:/Users/dge/Desktop/Database/NewPythonProject/html Grabber/chromedriver.exe')
for i in df.index:
print(i)
pic = path + df['site'][i] + '.png'
driver.get('http://' + df['site'][i])
time.sleep(5)
driver.save_screenshot(pic)
I've seen this but just not sure how to add it in the loop
driver.find_element_by_id('').click()
alert = driver.switch_to_alert()
The best way to put this may be to say ignore any errors and continue on through my list of urls.
JavaScript can create alert(), confirm() or prompt()
To press button OK
driver.switch_to.alert.accept() # press OK
To press button CANCEL (which exists only in confirm() and prompt())
driver.switch_to.alert.dismiss() # press CANCEL
To put some text in prompt() before accepting it
prompt = driver.switch_to.alert
prompt.send_keys('foo bar')
prompt.accept()
There is no function to check if alert is displayed
but you can put it in try/except to catch error when there is no alert.
try:
driver.switch_to.alert.accept() # press OK
#driver.switch_to.alert.dismiss() # press CANCEL
except Exception as ex:
print('Exception:', ex)
Minimal working example.
Because I don't know page which displays alert so I use execute_script to display it.
from selenium import webdriver
import time
#driver = webdriver.Firefox()
driver = webdriver.Chrome()
driver.get('http://google.com')
# --- test when there is alert ---
driver.execute_script("console.log('alert: ' + alert('Hello World!'))")
#driver.execute_script("console.log('alert: ' + confirm('Hello World!'))")
#driver.execute_script("console.log('alert: ' + prompt('Hello World!'))")
time.sleep(2)
try:
driver.switch_to.alert.accept() # press OK
#driver.switch_to.alert.dismiss() # press CANCEL
except Exception as ex:
print('Exception:', ex)
# --- test when there is no alert ---
try:
driver.switch_to.alert.accept() # press OK
#driver.switch_to.alert.dismiss() # press CANCEL
except Exception as ex:
print('Exception:', ex)
# ---
driver.save_screenshot('image.png')
driver.close()
BTW: if you want to first try to press CANCEL and when it doesn't work then press OK
try:
driver.switch_to.alert.dismiss() # press CANCEL
except Exception as ex:
print('Exception:', ex)
try:
driver.switch_to.alert.accept() # press OK
except Exception as ex:
print('Exception:', ex)
BTW: different problem can be popup notifications or geolocation alerts
How to click Allow on Show Notifications popup using Selenium Webdriver

Python-How to continue my test script even if some error comes

Here is my code. I wrote script which can test multiple test cases. This scripts throws an exception when an error comes however i want that it keeps the count of errors and their descriptions and log after test execution whether it is success or failed. More important is should run complete test script in any how.
from selenium import webdriver
from generic_functions.FindElement import HandyWrappers
from generic_functions.takescreenshots import Screenshot
from generic_functions.error_handle import CatchExceptions
import os
import time
import unittest
class TestEnrollment(unittest.TestCase):
driverLocation =
"C:\\Users\\Sales\\Desktop\\Automation\\Trendz\\libs\\chromedriver.exe"
os.environ["webdriver.chrome.driver"] = driverLocation
driver = webdriver.Chrome(driverLocation)
driver.maximize_window()
driver.implicitly_wait(10)
def test_login(self):
try:
baseURL = "https://portal.ABCD.com"
driver = self.driver
driver.get(baseURL)
hw = HandyWrappers(driver)
username = hw.getElement(".//form[#id='login-form']/fieldset/section[1]/label[2]/input[#name='email']",
locatorType="xpath")
username.send_keys("ABCD#live.com")
time.sleep(2)
password = hw.getElement(".//form[#id='login-form']/fieldset/section[2]/label[2]/input[#name='password']",
locatorType="xpath")
password.send_keys("ABCD09")
signIn = hw.getElement(".//form[#id='login-form']/footer/button[contains(text(),'Sign in')]",
locatorType="xpath")
signIn.click()
self.assertTrue(driver.find_element_by_xpath(".//header[#id='header']/section/div/div[#id='logout']/span/a12"), "Sign Out")
except Exception as err:
raise err
def test_menu_enr(self):
driver = self.driver
hw = HandyWrappers(driver)
find_enrollment = hw.getElement(".//aside[#id='left-panel']/nav/ul[14]/li/a/span", locatorType="xpath")
find_enrollment.click()
if __name__ == '__main__':
unittest.main()
Don't raise it, Use pass or continue
def test_login():
try:
...
except Exception:
# log the exception here
pass # or you could use 'continue'
Note: Have to look into this also diff bw pass and continue
collect all errors in some list and then assert error list at end of test
from selenium import webdriver
from generic_functions.FindElement import HandyWrappers
from generic_functions.takescreenshots import Screenshot
from generic_functions.error_handle import CatchExceptions
import os
import time
import unittest
class TestEnrollment(unittest.TestCase):
driverLocation = "C:\\Users\\Sales\\Desktop\\Automation\\Trendz\\libs\\chromedriver.exe"
os.environ["webdriver.chrome.driver"] = driverLocation
driver = webdriver.Chrome(driverLocation)
driver.maximize_window()
driver.implicitly_wait(10)
def setUp(self):
self.errors = []
def tearDown(self):
self.assertEqual([], self.errors)
def test_login(self):
try:
baseURL = "https://portal.ABCD.com"
driver = self.driver
driver.get(baseURL)
hw = HandyWrappers(driver)
username = hw.getElement(".//form[#id='login-form']/fieldset/section[1]/label[2]/input[#name='email']",
locatorType="xpath")
username.send_keys("ABCD#live.com")
time.sleep(2)
password = hw.getElement(".//form[#id='login-form']/fieldset/section[2]/label[2]/input[#name='password']",
locatorType="xpath")
password.send_keys("ABCD09")
signIn = hw.getElement(".//form[#id='login-form']/footer/button[contains(text(),'Sign in')]",
locatorType="xpath")
signIn.click()
self.assertTrue(driver.find_element_by_xpath(
".//header[#id='header']/section/div/div[#id='logout']/span/a12"), "Sign Out")
except Exception as err:
self.errors.append(err)
def test_menu_enr(self):
driver = self.driver
hw = HandyWrappers(driver)
find_enrollment = hw.getElement(
".//aside[#id='left-panel']/nav/ul[14]/li/a/span", locatorType="xpath")
find_enrollment.click()
if __name__ == '__main__':
unittest.main()
tearDown method will run at end and shows all error messages if any present
As for i know , this is not ideal solution. its kind of hack fix
If you're using selenium webdriver with Python unittest (looks like you are), the SeleniumBase framework has the nifty delayed_assert_text and delayed_assert_element methods built-in for processing test failures at the end of the test. You can install seleniumbase with pip, or clone the repo from github.
The following code is taken from this example.
from seleniumbase import BaseCase
class MyTestClass(BaseCase):
def test_delayed_asserts(self):
self.open('http://xkcd.com/993/')
self.wait_for_element('#comic')
self.delayed_assert_element('img[alt="Brand Identity"]')
self.delayed_assert_element('img[alt="Rocket Ship"]') # Will Fail
self.delayed_assert_element('#comicmap')
self.delayed_assert_text('Fake Item', '#middleContainer') # Will Fail
self.delayed_assert_text('Random', '#middleContainer')
self.delayed_assert_element('a[name="Super Fake !!!"]') # Will Fail
self.process_delayed_asserts()
Inside the script, there are multiple asserts that will fail, but only after self.process_delayed_asserts() is called. Here's the output after running it:
pytest delayed_assert_test.py
=============================== test session starts ===============================
platform darwin -- Python 3.6.5, pytest-3.7.3, py-1.5.4, pluggy-0.7.1
delayed_assert_test.py F
==================================== FAILURES =====================================
________________________ MyTestClass.test_delayed_asserts _________________________
E Exception:
E *** DELAYED ASSERTION FAILURES FOR: examples.delayed_assert_test.MyTestClass.test_delayed_asserts
E CHECK #2: (https://xkcd.com/993/)
E Element {img[alt="Rocket Ship"]} was not visible after 1 second!
E CHECK #4: (https://xkcd.com/993/)
E Expected text {Fake Item} for {#middleContainer} was not visible after 1 second!
E CHECK #6: (https://xkcd.com/993/)
E Element {a[name="Super Fake !!!"]} was not visible after 1 second!
Exception
============================ 1 failed in 7.53 seconds =============================

Selenium Webdriver: (python) wait for element to not be present (not working)

I'm learning about the Selenium web drivers and have started using python to test websites. I'm having issues with the wait for element not to be present code, as it seems to be timing out.
This is the code I have so far.
def test_(self):
driver = self.driver
driver.get(self.base_url + "/abc")
driver.find_element_by_id("UserName").clear()
driver.find_element_by_id("UserName").send_keys("username")
driver.find_element_by_id("Password").clear()
driver.find_element_by_id("Password").send_keys("password")
driver.find_element_by_id("loginbutton").click()
for i in range(60):
try:
if not self.is_element_present(By.CSS_SELECTOR, ".blockUI"): break
except: pass
time.sleep(1)
else: self.fail("time out")
driver.find_element_by_xpath(".//*[#id='ChangeTaskGridM']/table/thead/tr/th[1]/a").click()
for i in range(60):
try:
if not self.is_element_present(By.CSS_SELECTOR, ".blockUI"): break
except: pass
time.sleep(1)
else: self.fail("time out")
driver.find_element_by_xpath(".//*[#id='ChangeTaskGridM']/table/thead/tr/th[2]/a").click()
for i in range(60):
try:
if not self.is_element_present(By.CSS_SELECTOR, ".blockUI"): break
except: pass
time.sleep(1)
else: self.fail("time out")
I'm not sure why it's timing out. If I remove the blockUI it will run to fast and I also don't want to put manual breaks in between. Any ideas?
Current code to detect is_element_present
for i in range(60):
try:
if not self.is_element_present(By.CSS_SELECTOR, ".blockUI"): break
except: pass
time.sleep(1)
else: self.fail("time out")
Instead of your code to check presence of that element you should use ExpectedConditions. Please read the doc for waits. the presence_of_element_located() is probably the one of interest to you.
You put sleep in wrong place, i believe this is what you wanted:
for i in range(60):
try:
if not self.is_element_present(By.CSS_SELECTOR, ".blockUI"):
break
else:
time.sleep(1)
except: pass
also in Python else after for will be always performed after successful end of loop, no wonder you get self.fail("time out") every time

set a timout in python splinter web crawler

Trying to set a time out in python much like you would in ruby.
I have a link that when I click it opens a popup but I can not access it because it causes the script to freeze until I kill it. I have been trying for months to access this popup to no joy in ruby watir-webdriver.
I am trying to timeout the call to popup and then access the popup window.
#timeout(3)
try:
b.execute_script("javascript:openMdlWindow('InvestmentDetailOptions.aspx?IDAssetType=','620','600');if(window.document.RetValue == '2'){window.parent.LoadinIframe('InvestmentDetail.aspx?FromMenu=N&IDAssetType=','Investment Details > Full View','false');}")
except Exception, e:
print 'timeout!'
any help will be dearly appreciated.
Just try this:
from splinter import Browser
from selenium.common.exceptions import TimeoutException
b = Browser('firefox')
b.driver.set_page_load_timeout(1)
try:
b.visit('http://www.bbc.com')
except TimeoutException:
pass
print b.html
import signal
from time import sleep
class TimeoutException(Exception):
pass
def do_something_else():
time = 5
sleep(time)
return 'do_something_else has to run for %d seconds' % time
def handler(signum, frame):
raise TimeoutException
def do_something_with_timeout(callback, timeout=3):
signal.signal(signal.SIGALRM, handler)
signal.alarm(timeout)
try:
value = callback()
signal.alarm(0)
return value
except TimeoutException:
pass
signal.signal(signal.SIGALRM, signal.SIG_IGN)
return 'time out'
def main():
print 'hello'
print do_something_with_timeout(do_something_else)
print 'world'
main()

Categories