So I have this test and fixture:
#pytest.fixture()
def init_driver():
return webdriver.Chrome(executable_path=TestParams.CHROME_EXECUTABLE_PATH)
#pytest.mark.usefixtures('init_driver')
def test_1():
driver = init_driver
login(driver)
In this case my driver type is <class 'function'> so I cannot use its function for example get and got this error:
AttributeError: 'function' object has no attribute 'get'
When I change it to this:
#pytest.mark.usefixtures('init_driver')
def test_1():
login(webdriver.Chrome(executable_path=TestParams.CHROME_EXECUTABLE_PATH))
My driver type is <selenium.webdriver.chrome.webdriver.WebDriver (session="4ca3cb8f5bcec7a7498a65bfe5a2ea81")>
And all works fine.
What I am doing wrong ?
I fixed the syntax and changed it so that it runs without your hidden methods and variables such as login() and TestParams:
import pytest
from selenium import webdriver
#pytest.fixture()
def init_driver():
driver = webdriver.Chrome()
yield driver
driver.quit()
def test_1(init_driver):
driver = init_driver
print(type(driver))
Running that prints:
<class 'selenium.webdriver.chrome.webdriver.WebDriver'>
Related
I have a fixture file.
import pytest
from selenium.webdriver.chrome.options import Options as chrome_options
from driver.singleton_driver import WebDriver
#pytest.fixture
def get_chrome_options():
options = chrome_options()
options.add_argument('chrome')
options.add_argument('--start-maximized')
options.add_argument('--window-size=1920,1080')
options.add_argument('--incognito')
return options
#pytest.fixture
def get_webdriver(get_chrome_options):
options = get_chrome_options
driver = WebDriver(options).driver
return driver
#pytest.fixture(scope='function')
def setup(request, get_webdriver):
driver = get_webdriver
if request.cls is not None:
request.cls.driver = driver
yield driver
driver.close()
File with my tests
import pytest
#pytest.mark.usefixtures('setup')
class TestSteamPages:
def test_first(self):
self.driver.get('https://www.google.com/')
def test_second(self):
self.driver.get('https://www.google.com/')
As I understand it, after the first test, the function in the driver.close() fixture is triggered. But when the second test is run, the fixture does not restart the webdriver. An error
venv/lib/python3.10/site-packages/selenium/webdriver/remote/errorhandler.py:243: InvalidSessionIdException
============================================================================== short test summary info ==============================================================================
FAILED tests/test_first.py::TestSteamPages::test_second -
selenium.common.exceptions.InvalidSessionIdException: Message: invalid session id
ERROR tests/test_first.py::TestSteamPages::test_second - selenium.common.exceptions.InvalidSessionIdException: Message: invalid session id
For the driver, I use the Singleton pattern
from selenium import webdriver
from selenium.webdriver.chrome.service import Service as ChromeService
from webdriver_manager.chrome import ChromeDriverManager
class WebDriver:
class __WebDriver:
def __init__(self, options):
self.driver = webdriver.Chrome(options=options, service=ChromeService(ChromeDriverManager().install()))
driver = None
def __init__(self, options):
if not self.driver:
WebDriver.driver = WebDriver.__WebDriver(options=options).driver
The driver is not reinitialized because of the singleton. WebDriver.driver is initialized before first test, so in the next time setup is running if not self.driver is False, because self.driver is not None anymore.
If you want to initialize the WebDriver every test don't use singleton
#pytest.fixture
def get_webdriver(get_chrome_options):
options = get_chrome_options
driver = webdriver.Chrome(options=options, service=ChromeService(ChromeDriverManager().install()))
return driver
If you do want to initialize the WebDriver only once you can change fixtures scope to 'class' (for all tests in TestSteamPages) or even move it to conftest.py with scope 'session' for one driver instance for all the test. Note that in this case all the fixtures need to have scope='class'
#pytest.fixture(scope='class')
def setup(request, get_webdriver):
driver = get_webdriver
if request.cls is not None:
request.cls.driver = driver
yield driver
driver.close()
I am using Unittest + Pytest. I need perfrom move over.
Here is first page:
from selenium import webdriver
from selenium.webdriver.common.by import By
import pytest
import unittest
from page.home.main_page import MainPage
from selenium.webdriver import ActionChains
class MainPageTests(unittest.TestCase):
def setUp(self):
baseURL = "https://grin.co/"
driver = webdriver.Chrome()
driver.maximize_window()
driver.implicitly_wait(3)
driver.get(baseURL)
self.mb = MainPage(driver)
self.driver = driver
#pytest.mark.run(order=1)
def testtitle(self):
self.mb.creatormenu()
Here is second:
from selenium.webdriver.common.by import By
from selenium.webdriver import ActionChains
import time
class MainPage():
def init(self,driver):
self.driver = driver
def creatormenu(self):
time.sleep(2)
element = self.driver.find_element(By.ID, "menu-item-17096")
actions = ActionChains(self)
actions.move_to_element(element).perform()
print("Mouse Hovered on element")
And I gets error:
device.actions = []
self.driver.execute(Command.W3C_ACTIONS, enc)
E AttributeError: 'MainPage' object has no attribute 'execute'
venv/lib/python3.8/site-packages/selenium/webdriver/common/actions/action_builder.py:88: AttributeError
======================================================================================= short test summary info ========================================================================================
FAILED Tests/home/mane_page_test.py::MainPageTests::testtitle - AttributeError: 'MainPage' object has no attribute 'execute'
What did I miss?
Thank you in advance
Thank you for posting your answer Oleg!
I had the same issue when tried to use the following functions without ".driver":
def switchToNewWindow(self):
remote = Remote(self.driver)
remote.switch_to.window(remote.window_handles[1])
and
def moveSlideBar(self, Xamount, Yamount, locator):
move = ActionChains(self.driver)
move.click_and_hold(locator).move_by_offset(Xamount, Yamount).release().perform()
I am learning selenium in python with pytest, I am facing this below error. I have searched this error all over the internet and tried all the possible advice, but nothing is working.
I am just trying to load the website, it is opening the browser but failing with this error. I don't know what i am missing, Any lead would be helpful.
FAILED Tests/test_webtable.py::test_webtablepage - AttributeError: type object 'WebTablePage' has no attribute 'load'
Code
Page Object Class(webtablepage.py) under pages folder.
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
class WebTablePage:
#URL
URL = 'https://demoqa.com/webtables'
#Intializers
def __init__(self,browser):
browser = self.browser
def load(self,browser):
self.browser.get(self.URL)
Pytest fixture(conftest.py) under Tests folder.
import pytest
import selenium.webdriver
#pytest.fixture
def browser():
#initialize the chrome instance
driver = selenium.webdriver.Chrome()
#Making the Driver wait for 10 seconds to load elements
driver.implicitly_wait(10)
#Return the webdriver instances for the setup
yield driver
#Quit the webdriver instances for the cleanup
driver.quit()
Test function (test_webtable.py) under Tests folder
from Pages.webtablepage import WebTablePage
def test_webtablepage(browser):
Webtable_page = WebTablePage
# Given the demoa qa Webtables page
Webtable_page.load()
The WebTablePage constructor is called incorrectly. It must be called with the browser argument.
Change this:
def test_webtablepage(browser):
Webtable_page = WebTablePage
To this:
def test_webtablepage(browser):
Webtable_page = WebTablePage(browser)
Change the
Webtable_page = WebTablePage
to
Webtable_page = WebTablePage()
I've been looking for a solution to inherit the methods of the python selenium webdriver class so that I can extend/modify its behaviour. I have not found one that work.
For instance, I want to inherit all the methods of the chrome webdriver but extend the .get() method (i.e. the method to load a url). This is my current approach:
from selenium import webdriver
from selenium.common.exception import TimeoutException
class CustomDriver:
def __init__(self, browser):
if browser.lower() == 'chrome'
self.driver = webdriver.Chrome()
def get_url(self, url):
try:
self.driver.get(url)
except TimeoutException:
self.driver.quit()
This methods works but it does not inherit the general webdriver methods like driver.quit(). In fact, if I do the following:
mydriver = CustomDriver('Chrome')
mydriver.quit()
I get the error: 'Custom driver' object has no attribute quit.
Has any of you any suggestions?
ps: I'm new to python.
quit() is from webdriver methods and you are importing it from selenium module, and you have created a object self.driver for the webdriver.Chrome()
so you can't use webdriver method on created class object that is the reason why you are getting No Attribute Error : 'Custom driver' object has no attribute quit
One way of obtaining inheritance is by declaring respective method inside the class and inherit those methods outside.
Refer this document: https://www.geeksforgeeks.org/web-driver-methods-in-selenium-python/
Below is the code that would work
from selenium import webdriver
from selenium.common.exceptions import TimeoutException
class CustomDriver:
def __init__(self, browser):
if browser.lower() == 'chrome':
self.driver = webdriver.Chrome()
def exit_browser(self):
self.driver.quit()
def get_url(self, url):
try:
self.driver.get(url)
except TimeoutException:
self.driver.quit()
mydriver = CustomDriver('Chrome')
mydriver.get_url("https://www.google.com/")
mydriver.exit_browser()
Getting error for line self.driver.executes_script
self.driver.executes_script("arguments[0].click();", new_notification)
AttributeError: 'WebDriver' object has no attribute 'executes_script'
None
but their is a class name with it
import unittest
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import HtmlTestRunner
import time
class Environment(unittest.TestCase):
def setUp(self):
self.driver = webdriver.Chrome(executable_path="F:\\automation\\chromedriver.exe")
# login test case
def test_first_page_login(self):
driver = self.driver
driver.maximize_window()
driver.get("http://localhost/dashboard/user/login")
self.driver.find_element_by_id('uemail').send_keys('xyz#abc.com')
self.driver.find_element_by_id('upwd').send_keys('1234567890')
self.driver.find_element_by_id('upwd').send_keys(Keys.RETURN)
# login page going
def test_going_notification_page(self):
self.test_first_page_login()
time.sleep(5)
going_noti_page = self.driver.find_element_by_class_name('caret')
print(self.driver.execute_script("arguments[0].click();", going_noti_page))
new_notification = self.driver.find_element_by_class_name('fa-paper-plane')
self.driver.executes_script("arguments[0].click();", new_notification)
time.sleep(5)
def tearDown(self):
self.driver.quit()
if __name__ == "__main__":
unittest.main(testRunner=HtmlTestRunner.HTMLTestRunner(output='F:\\automation\\reports'))
you just have a typo:
self.driver.executes_script("arguments[0].click();", new_notification)
executes_script doesn't exist, but based on the api-doc you probably mean: execute_script
DOC: WebDriver.execute_script