How to pass Selenium WebDriver instances between functions in Python? - python

I have a function that handles logging into a website. I then return the webdriver instance so that I can pass it into another fucnction that actually handles getting the information that I need.
For some reason I have been unable to call my second function using the returned driver instance.
Was wondering if anyone had any insight into how I can pass a webdriver instance to another function? Thanks.

how I can pass a webdriver instance to another function?
You would return the instance from the first function and call the second function with it.
In the example below, I define 2 functions. A webdriver is instantiaterd inside func1, which returns the instance. Then I call func2, which takes a driver instance as an argument.
from selenium import webdriver
def func1():
driver = webdriver.Chrome()
driver.get('https://example.com')
return driver
def func2(driver):
return driver.title
if __name__ == '__main__':
driver = func1()
title = func2(driver)
print(title)
driver.quit()
This code will launch a browser (Chrome), navigate to a site (https://example.com), print the page title ("Example Domain"), and then quit the browser.

Alternatively, extending Corey Goldberg's answer. It is perfectly fine to simply pass a reference of the driver to all functions that use it.
from selenium import webdriver
def func1(driver):
driver.get('https://example.com')
def func2(driver):
return driver.title
if __name__ == '__main__':
driver = webdriver.Chrome()
func1(driver)
title = func2(driver)
print(title)
driver.quit()

Related

Calling Function From Another File Does Not Recognise Defined Name

I'm new to python and selenium. I want to call a login function from another file and then continue my test within the same driver. I've managed to write a login function > call it from the other file but when I continue with my test, i get the following error, NameError: name 'driver' is not defined
How can I make this work so I can reference the login function to login and then continue writing code without getting the NameError?
Here is the code
file1.py
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
def login(context):
s = Service("C:pythonProject/chromedriver.exe")
# Starts the chrome driver
global driver
driver = webdriver.Chrome(service=s)
driver.maximize_window()
def username(context):
# URL
url = "https://www.bbc.com"
driver.get(url)
driver.implicitly_wait(10)
search = driver.find_element(By.ID, "user")
search.send_keys('xxxxx')
search = driver.find_element(By.ID, "pass")
search.send_keys('xxxxx')
driver.find_element(By.ID, "log_in_button").click()
file2.py
from behave import *
from file1 import *
from selenium.webdriver.common.by import By
#given(u'sdsd')
def step_impl(context):
login(context)
username(context)
#when(u'sdds')
def step_impl(context):
search = driver.find_element(By.ID, "headerBar")
Not even from … import * can give you access to names added by global after the import occurs. (Worse still, if they are reassigned, you’ll still have the old value.)
Just take that as yet another reason not to use that syntax: write
import file1
…:
search = file1.driver.find_element(By.ID, "headerBar")
or better yet have the file1 functions return driver rather than storing it in a global at all.

How can I pass argument as part of selenium webdriver command

I have below similar codes. The only difference is the browser I choose. I want to combine the duplicated codes into a function.
driver = webdriver.Chrome()
driver.get('http://www.google.ca')
driver.quit()
driver2 = webdriver.Firefox()
driver2.get('http://www.google.com')
time.sleep(2)
driver2.quit()
I wrote the below function but seems cannot pass the browser_name as part of the command. Any solution for this?
def go_to_baidu(browser_name):
driver = webdriver.browser_name()
driver.get('http://www.baidu.com')
time.sleep(2)
driver.quit()
Instead of passing a value like "Chrome" or "Firefox" to your function, pass webdriver.Chrome or webdriver.Firefox() (without the quotes) instead. The, change the first line of the function like so:
def go_to_baidu(browser_name):
driver = browser_name()
driver.get('http://www.baidu.com')
time.sleep(2)
driver.quit()
You then run it like this:
go_to_baidu(webdriver.Chrome)
for example.
Functions are objects in Python, and can be passed to other functions just as easily as strings, lists, dicts, etc. can.

I am getting the exception while running below code

from selenium import webdriver
from selenium.webdriver.common.keys import Keys
driver=webdriver.chrome(executable_path="C:\Driver\chromedriver_win32\chromedriver.exe")
driver.get("www.youtube.com")
print (driver.title)
driver.close()
for the above code I'm getting the error
TypeError: 'module' object is not callable
I recommend modular programming.
Set a function that returns the chrome driver like such:
# Opens chrome driver
def openChrome():
# directory to chromedrive
chromeDriver = "C:\Driver\chromedriver_win32\chromedriver.exe"
return webdriver.Chrome(chromeDriver)
Call this function like this:
url = "https://stackoverflow.com/"
driver = openChrome()
driver.get(url)
So in the future if your driver isn't working, you don't have to change it on every script you will change it in one place (function)

Error while switching window in python selenium

I want to work with multiple windows and tabs using selenium and python.
I am getting below error during script execution:-
( code is mentioned at last)
{f625f26d-cfcf-442c-b9fc-5e96a199cd43}
C:\Python34\lib\site-packages\selenium-2.47.1- py3.4.egg\selenium\webdriver\remot
e\webdriver.py:525: DeprecationWarning: use driver.switch_to.window instead
warnings.warn("use driver.switch_to.window instead", DeprecationWarning)
{cad6e3cf-9062-408e-a6f1-11e98813dc6c}
import unittest
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By
class GoogleTabs(unittest.TestCase):
def setUp(self):
self.driver = webdriver.Firefox()
def test_google_search_page(self):
driver = self.driver
driver.get("http://www.cdot.in")
window_before = driver.window_handles[0]
print (window_before)
driver.find_element_by_xpath("//a[#href='http://www.cdot.in/home.htm']").click()
window_after = driver.window_handles[1]
driver.switch_to_window(window_after)
print (window_after)
driver.find_element_by_link_text("ATM").click()
driver.switch_to_window(window_before)
def tearDown(self):
self.driver.close()
if __name__ == "__main__":
unittest.main()
As the warning says
DeprecationWarning: use driver.switch_to.window instead
you'll need to change your
driver.switch_to_window
with
driver.switch_to.window
But think about it: it is a warning, not an error! Your code should work, it is just telling you that that method is deprecated.
You're getting a warning message, for new versions of selenium the method has changed.
Instead of using: driver.switch_to_window(window)
Try with: driver.switch_to.window
Where window is your variable.
I propose a very simple way to switch between windows without any hassles of playing with the handles yourself. https://gist.github.com/ab9-er/08c3ce7d2d5cdfa94bc7
def change_window(browser):
"""
Simple window switcher without the need of playing with ids.
#param browser: Current browser instance
"""
curr = browser.current_window_handle
all_handles = browser.window_handles
for handle in list(set([curr]) - set(all_handles)):
return browser.switch_to_window(handle)

Wait for element to load when testing an iOS app using Appium and Python?

I am testing a native iOS app and need to wait for some elements to load in some of my testing. Appium is going too fast on some screens right now.
Can someone please point me to an example of using a WebDriverWait style of waiting for Appium iOS testing? There was a question that was answered for Ruby here: Wait for element to load when testing an iOS app using Appium and Ruby?. Looking for something similar in Python.
The Python client documentation doesn't seem to document the wait functions.
Thanks.
At the top of the test import these.
from appium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
TL/DR is this should work, you may have to change self.driver to just driver in the wait = section depending on how you're doing things. Also, obviously change the By.XPath to whatever locator you're using:
wait = WebDriverWait(self.driver, 20)
currently_waiting_for = wait.until(EC.element_to_be_clickable((By.XPATH,'//UIAApplication[1]/UIAWindow[1]/UIAButton[#text="example text"]')))
Or you could just tell the driver to use implicit waits.
self.driver.implicitly_wait(10)
myElement = driver.find_element_by_id("fakeid")
myElement.click()
Most of this is explained here.
Here's an example of using wait to log into an Android App (Haven't used it on ios but it should be the similar) using the default account selector then asserting the right text appeared. During the setup, I'm loading my desired capabilities from another file.
class TrainUpSmokeTests(unittest.TestCase):
def setUp(self):
desired_caps = desired_capabilities.get_desired_capabilities('app-debug.apk')
self.driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps)
def tearDown(self):
self.driver.quit()
def example_test(self):
wd = self.driver
## Depending on how you're running the test the first variable may just be driver. Or in my case self.driver which I shortened above. The number is how many seconds it should wait before timing out.
wait = WebDriverWait(wd, 20)
## Waiting for account selector to be clickable.
currently_waiting_for = wait.until(EC.element_to_be_clickable((By.XPATH,'//android.widget.CheckedTextView[#text="FakeEmail#example.com"]')))
## Locating test account and selecting it.
account = wd.find_element_by_android_uiautomator('text("FakeEmail#example.com")')
account.click()
ok_button = wd.find_element_by_android_uiautomator('text("OK")')
ok_button.click()
## Waiting for an Element on the home screen to be locatable.
currently_waiting_for = wait.until(EC.presence_of_element_located((By.XPATH,'//android.widget.RelativeLayout[#resource-id="com.name.app:id/overview"]')))
hero_headline = wd.find_element_by_android_uiautomator('new UiSelector().description("Example Header")')
self.assertIsNotNone(hero_headline)
if __name__ == '__main__':
suite = unittest.TestLoader().loadTestsFromTestCase(TrainUpSmokeTests)
unittest.TextTestRunner(verbosity=2).run(suite)
It's a your testings a website using appium (instead of an app). Change the setup so self.driver opens a browser.
self.driver = webdriver.Firefox()
And then use By selectors like class, name, id, e.g. the example below.
currently_waiting_for = wait.until(EC.element_to_be_clickable((By.CLASS_NAME,'search-results')))
This article also helped. Also if you don't know how to find xpaths, look into setting up uiautomatorviewer that comes with appium.
The python usage is:
driver.implicitly_wait(timeToWaitSec)
Selenium sourcecode(Py)
You can use WaitForElement class:
class WaitForElement:
#staticmethod
def wait(driver, id, time_out=100):
try:
WebDriverWait(driver, time_out).until(
lambda driver: driver.find_element(*id))
except TimeoutException:
print('Not able to find ID:' + id)
You can find all you need in selenium.webdriver.support.expected_conditions
Then from it you can do something like:
def wait_for_element_visible(self, by=By.XPATH, value=None, text=None, wait_time=20):
if text is not None:
value = value % text
wait = WebDriverWait(self.driver, wait_time)
return wait.until(EC.visibility_of_element_located((by, value)))
You can use implicitWait. Something like remoteWebDriver.implicitlyWait(time, timeUnit) This of course is for java. Something similar should be available for python.

Categories