Calling Function From Another File Does Not Recognise Defined Name - python

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.

Related

Facing this error in Pytest on selenium python

import time
import self as self
from pytest import mark
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By
from setuptools import setup
#mark.execute
class First_Tests:
def test_first(self, setup):
driver = setup['driver']
browser = setup['browser']
driver.get("https://shuftipro.com/")
driver.maximize_window()
def header_test(self, setup):
driver = setup['driver']
# Click on solution in header
solution = driver.find_element(By.ID, "menu-item-72751")
solution.click()
if driver.current_url == "https://shuftipro.com/solutions/":
print("land on solution page.")
else:
print("land on wrong page.")
obj = First_Tests()
obj.test_first(self, setup)
obj.header_test(self, setup)
If I remove the "self" from parameter and run the program it showing me error that, test_first() takes 1 positional arguments but 3 were given
one of easier way would be to use webdriver from selenium
driver = webdriver.Chrome()
and remove
driver = setup['driver']
browser = setup['browser']
and then get rid of setup as parameter.
The final code will look something like this:
from pytest import mark
from selenium import webdriver
from selenium.webdriver.common.by import By
driver = webdriver.Chrome()
#mark.execute
class First_Tests:
def test_first(self):
driver.get("https://shuftipro.com/")
driver.maximize_window()
def header_test(self):
# Click on solution in header
solution = driver.find_element(By.ID, "menu-item-72751")
solution.click()
if driver.current_url == "https://shuftipro.com/solutions/":
print("land on solution page.")
else:
print("land on wrong page.")
obj = First_Tests()
obj.test_first()
obj.header_test()

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)

Why Microsoft VS Code throws an error? How to make sure that many windows do not open, but everything is done in one window?

Good day.
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.action_chains import ActionChains
import time
def automation_func(url, i):
driver = webdriver.Chrome()
driver.maximize_window()
time.sleep(3)
driver.get("https://site.ru")
btn_elem1 = driver.find_element_by_xpath("/html/body/div[2]/div[3]/div[2]/div[1]/div/ul/li[2]")
btn_elem1.click()
btn_elem2 = driver.find_element_by_xpath("/html/body/div[2]/div[3]/div[2]/div[1]/div/div[2]/div/p[1]/label/input")
btn_elem2.click()
btn_elem2.send_keys("login")
btn_elem3 = driver.find_element_by_xpath("/html/body/div[2]/div[3]/div[2]/div[1]/div/div[2]/div/p[2]/label/input")
btn_elem3.click()
btn_elem3.send_keys("pass")
btn_elem4 = driver.find_element_by_xpath("/html/body/div[2]/div[3]/div[2]/div[1]/div/div[2]/div/a")
btn_elem4.click()
time.sleep(3)
driver.get(url)
btn_elem5 = driver.find_element_by_xpath("/html/body/div[1]/div[3]/div[1]/fieldset/div[2]/img[1]")
btn_elem5.click()
time.sleep(5)
if "Даво" in driver.page_source:
screenshot = driver.save_screenshot("{i}.png")
def main():
for i in range(4, 12000):
automation_func(f"https://site.ru/lookup/{i}", i)
if __name__ == "__main__":
main()
Example above - everything works, but every time a new window opens. Everything is clear, because it is written in the function.
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.action_chains import ActionChains
import time
def main():
driver = webdriver.Chrome()
driver.maximize_window()
time.sleep(3)
driver.get("https://site.ru")
btn_elem1 = driver.find_element_by_xpath("/html/body/div[2]/div[3]/div[2]/div[1]/div/ul/li[2]")
btn_elem1.click()
btn_elem2 = driver.find_element_by_xpath("/html/body/div[2]/div[3]/div[2]/div[1]/div/div[2]/div/p[1]/label/input")
btn_elem2.click()
btn_elem2.send_keys("login")
btn_elem3 = driver.find_element_by_xpath("/html/body/div[2]/div[3]/div[2]/div[1]/div/div[2]/div/p[2]/label/input")
btn_elem3.click()
btn_elem3.send_keys("pass")
btn_elem4 = driver.find_element_by_xpath("/html/body/div[2]/div[3]/div[2]/div[1]/div/div[2]/div/a")
btn_elem4.click()
def automation_func(url, i):
driver.get(url)
time.sleep(3)
btn_elem5 = driver.find_element_by_xpath("/html/body/div[1]/div[3]/div[1]/fieldset/div[2]/img[1]")
btn_elem5.click()
time.sleep(5)
if "Даво" in driver.page_source:
screenshot = driver.save_screenshot("{i}.png")
def main():
for i in range(4, 12000):
automation_func(f"https://site.ru/lookup/{i}", i)
if __name__ == "__main__":
main()
Here I wanted to display it separately. So that the function contains only what is needed. To prevent many windows from opening. Since you have to go over more than 10 thousand pages. Gives an error message.
There is always one mistake. driver and main are underlined. If you put different indents, then something gets better there, then another error. In general, it already seems to have gone through all the options.
Undefined variable 'driver'
Undefined variable 'driver'
Undefined variable 'driver'
Undefined variable 'driver'
function already defined line 9
Unused variable 'screenshot'
There is also a suspicion that the screenshot does not work. Or I didn't find the path where the images are saved.
Few things for you to consider:
You have two main() functions.
When you execute the script and try to call main(), which one do you expect to be called?
I suggest you rename the first one after it's purpose (e.g. CreateDriver or SetUpWedriver or such)
Your automation_func() has no context of driver. That's why you'll be getting so many undefined errors around it.
In your first main (the one to rename) you have
def main():
driver = webdriver.Chrome()
...
That line initialises the variable called "driver". That variable only exists in the context of that function. Once the function finishes all the variables are destroyed to release the memory.
Compare that to your first block of code where all the actions are done in a single block of code - therefore they all know what driver is.
With that variable-context in mind consider that you have:
def automation_func(url, i):
driver.get(url)
How will this function know what driver is? It has not been initiated.
The answer to this is to declare the variable outside the function - this makes it accessible everywhere.
Top of your script will look like this:
#...other imports
from selenium.webdriver.common.action_chains import ActionChains
import time
driver = webdriver.Chrome()
#note - renamed! - used to be main()
def CreateDriver():
driver.maximize_window()
time.sleep(3)
#rest of code below
Finally - The site you provide in the code doesn't work for me. That means i can't fully test it, but putting the above pieces together, I think you might want this:
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.action_chains import ActionChains
import time
#Note - moved outside the functions so it's accessible to all
driver = webdriver.Chrome()
#note - renamed! - this is not responsible for setting up the driver
def CreateDriver():
driver.maximize_window()
time.sleep(3)
driver.get("https://site.ru")
btn_elem1 = driver.find_element_by_xpath("/html/body/div[2]/div[3]/div[2]/div[1]/div/ul/li[2]")
btn_elem1.click()
btn_elem2 = driver.find_element_by_xpath("/html/body/div[2]/div[3]/div[2]/div[1]/div/div[2]/div/p[1]/label/input")
btn_elem2.click()
btn_elem2.send_keys("login")
btn_elem3 = driver.find_element_by_xpath("/html/body/div[2]/div[3]/div[2]/div[1]/div/div[2]/div/p[2]/label/input")
btn_elem3.click()
btn_elem3.send_keys("pass")
btn_elem4 = driver.find_element_by_xpath("/html/body/div[2]/div[3]/div[2]/div[1]/div/div[2]/div/a")
btn_elem4.click()
def automation_func(url, i):
CreateDriver # this gets the driver into the state we want
driver.get(url)
time.sleep(3)
btn_elem5 = driver.find_element_by_xpath("/html/body/div[1]/div[3]/div[1]/fieldset/div[2]/img[1]")
btn_elem5.click()
time.sleep(5)
if "Даво" in driver.page_source:
screenshot = driver.save_screenshot("{i}.png")
def main():
for i in range(4, 12000):
automation_func(f"https://site.ru/lookup/{i}", i)
if __name__ == "__main__":
main()
Last note - your additional question: Your screenshot does work.
You're not specifying a path, so when your code reaches that point it creates the screenshot in the same directory as the python file that is being executed.
If you're not seeing the screenshot, it's most likely because that line of code hasn't run yet or your IF function doesn't meet the right condition.

Python Selenium - Using same driver instance which is initiated in another file

In first file , there is a below code.
I want to use the driver instance of first file in second file , I am able to call it but getting an exception Nosuchelementexception
Basically i want the same browser session in both files , note that import statements are provided properly to use those.
class Init():
driver = webdriver.Chrome(
executable_path="C:\Program Files (x86)\Python36-32\selenium\webdriver\chromedriver_win32\chromedriver.exe")
def take_screenshot(self):
Init.driver.get_screenshot_as_png("Testcase.png")
def browser_launch(self):
Init.driver.set_page_load_timeout(20)
Init.driver.get("http://url/")
Init.driver.maximize_window()
def user_comes_in(self):
Init.driver.find_element_by_id("username").send_keys("admin")
Init.driver.find_element_by_name("password").send_keys("admin")
Init.driver.find_element_by_class_name("Button").click()
Init.driver.set_page_load_timeout(20)
In second file , here is the code
initiate = Init()
class Two(unittest.TestCase):
initiate.browser_launch()
def test_user_logs(self):
initiate.user_comes_in()
print("test case one")
def test_user_create(self):
initiate.user_creation()
print("Test case two")
if you can keep the browser open, you can do it like this:
init.py:
def setDriver():
driver = webdriver.Firefox()
driver.maximize_window()
driver = setDriver()
1.py:
from init.py import driver
driver.get('xxxx')
2.py:
from init.py import driver
driver.get('yyyy')
they will use same driver and same browser.
but if you close the driver in any of the case file, others can't use it again. so it only available in cases don't need to close browser.

How to properly close a Selenium WebDriver instance in python?

I am writing a script that will check if the proxy is working. The program should:
1. Load the proxy from the list (txt).
2. Go to any page (for example wikipedia)
3. If the page has loaded (even not completely) it saves the proxy data to another txt file.
It must all be in the loop. It must also check whether the browser has displayed an error. I have a problem with always turning off the previous browser every time, after several loops several browsers are already open.
Ps. I replaced the iteration with a random number
from selenium import webdriver
import random
from configparser import ConfigParser
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
import traceback
while 1:
ini = ConfigParser()
ini.read('liczba_proxy.ini')
random.random()
liczba_losowa = random.randint(1, 999)
f = open('user-agents.txt')
lines = f.readlines()
user_agent = lines[liczba_losowa]
user_agent = str(user_agent)
s = open('proxy_list.txt')
proxy = s.readlines()
i = ini.getint('liczba', 'liczba')
prefs = {"profile.managed_default_content_settings.images": 2}
chrome_options = webdriver.ChromeOptions()
chrome_options.add_argument('--proxy-server=%s' % proxy[liczba_losowa])
chrome_options.add_argument(f'user-agent={user_agent}')
chrome_options.add_experimental_option("prefs", prefs)
driver = webdriver.Chrome(chrome_options=chrome_options, executable_path='C:\Python\Driver\chromedriver.exe')
driver.get('https://en.wikipedia.org/wiki/Replication_error_phenotype')
def error_catching():
print("error")
driver.stop_client()
traceback.print_stack()
traceback.print_exc()
return False
def presence_of_element(driver, timeout=5):
try:
w = WebDriverWait(driver, timeout)
w.until(EC.presence_of_element_located((By.ID, 'siteNotice')))
print('work')
driver.stop_client()
return True
except:
print('not working')
driver.stop_client()
error_catching()
Without commenting on your code design:
In order to close a driver instance, use driver.close() or driver.quit() instead of your driver.stop_client().
The first one closes the the browser window on which the focus is set.
The second one basically closes all the browser windows and ends the WebDriver session gracefully.
Use
chrome_options.quit()
Obs.: Im pretty sure you should not use testcases like that... "while 1"? so you test will never end?
I guess you should setup your testes in TestCases and call the TheSuite to teste all your testcases and give you one feedback about whant pass or not, and maybe setup one cronjob to keep calling it by time to time.
Here one simple example mine using test cases with django and splinter (splinter is build on top of selenium)
https://github.com/Diegow3b/python-django-basictestcase/blob/master/myApp/tests/test_views.py

Categories