Python Forum
Selenium Page Object Model with Python
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Selenium Page Object Model with Python
#1
I am currently working with selenium and some boilerplatte code from github: https://github.com/gunesmes/page-object-python-selenium
After changing the code to work with a diffrent site I need to make a new function and I encoutererd a problem.


after using "click_sign_in_button" function in MainPage class I return the LoginPage instance to the Unittest and then try to login in the Website. If get an error I need to restart the page with BasePage class and again use the MainPage class function for the "click_sign_in_button", but if I try to import the class in LoginPage Class file I get an error and cant use the "click_sign_in_button" function.

I need to access parent class function to use a specific function again.
Reply
#2
Can you provide the code with the errors as well? It's kind of hard to help you without it.
Reply
#3
test_sign_in_page.py
from tests.base_test import BaseTest from pages.main_page import MainPage class TestSignInPage(BaseTest): def test_sign_in_with_in_valid_user(self): main_page = MainPage(self.driver) login_page = main_page.login_click() result = login_page.login()
main_page.py
from pages.base_page import BasePage from pages.login_page import LoginPage from utils import users from utils.locators import * class MainPage(BasePage): def __init__(self, driver): print("user_page __init__") self.locator = UserPageLocators self.user = users.get_user("google") super().__init__(driver) # Python3 version def check_page_loaded(self): return True if self.find_element(*self.locator.LOGO) else False def click_sign_in_button(self): self.find_element(*self.locator.LOGIN).click() def click_facebook_login_button(self): self.find_element(*self.locator.FACEBOOK_LOGIN).click() def click_google_login_button(self): self.find_element(*self.locator.GOOGLE_LOGIN).click() def click_apple_login_button(self): self.find_element(*self.locator.APPPLE_LOGIN).click() def switch_to_login_iframe(self): self.iframe = self.find_element(*self.locator.IFRAME) self.switch_iframe(self.iframe) def login_click(self): self.click_sign_in_button() self.switch_to_login_iframe() if self.user["provider"] == "google": self.click_google_login_button() elif self.user["provider"] == "facebook": self.click_facebook_login_button() elif self.user["provider"] == "apple": self.click_apple_login_button() return LoginPage(self.driver, self.user)
login_page.py
import time from utils.locators import * from pages.base_page import BasePage class LoginPage(BasePage): def __init__(self, driver, user): self.user = user if self.user["provider"] == "google": self.locator = GoogleLoginPageLocators elif self.user["provider"] == "facebook": self.locator = FacebookLoginPageLocators elif self.user["provider"] == "apple": self.locator = AppleLoginPageLocators super().__init__(driver) def enter_email(self, email): self.find_element(*self.locator.EMAIL).send_keys(email) def enter_password(self, password): self.find_element(*self.locator.PASSWORD).send_keys(password) def click_login_button(self): self.find_element(*self.locator.SUBMIT).click() def click_continue_button(self): self.find_element(*self.locator.CONTINUE).click() def switch_window(self, x): self.driver.switch_to.window(self.driver.window_handles[x]) def login(self): if self.user["provider"] == "google": self.login_google() elif self.user["provider"] == "facebook": self.login_facebook() elif self.user["provider"] == "apple": self.login_apple() if self.check_element(*self.locator.IFRAME): self.age_gender_verification() else: print("wtf") def age_gender_verification(self): #change frame for verification self.iframe = self.find_element(*self.locator.IFRAME) self.switch_iframe(self.iframe) #enter age self.find_element(*self.locator.AGE).send_keys(self.user["age"]) #enter gender self.find_element(*self.locator.GENDER_SELECT).click() if self.user["gender"] == "male": self.find_element(*self.locator.GENDER_MALE).click() else: self.find_element(*self.locator.GENDER_FEMALE).click() #Click Validation Continue self.find_element(*self.locator.VALIDATION_CONTINUE).click() #If error then restart the login proccess if self.check_element(*self.locator.VALIDATION_ERROR): from pages.main_page import MainPage #switch back from iframe self.driver.switch_to.default_content() #click close self.find_element(*self.locator.VALIDATION_CLOSE).click() #relogin MainPage(self).login_click() else: print("fail") def login_facebook(self): self.switch_window(1) print(self.user) self.enter_email(self.user["email"]) self.enter_password(self.user["password"]) self.click_login_button() self.switch_window(0) def login_google(self): self.switch_window(1) print(self.user) self.enter_email(self.user["email"]) self.click_continue_button() time.sleep(1) self.enter_password(self.user["password"]) self.click_login_button() self.switch_window(0) def login_apple(self): self.switch_window(1) print(self.user) self.enter_email(self.user["email"]) self.enter_password(self.user["password"]) self.click_login_button() self.switch_window(0)
Error Message:
Error:
ImportError: cannot import name 'LoginPage' from partially initialized module 'pages.login_page' (most likely due to a circular import)
for the missing classes please look at the github link https://github.com/gunesmes/page-object-python-selenium
Reply
#4
try to replace imports in test_sign_in_page.py to:
from tests.base_test import BaseTest from pages.main_page import MainPage
and then you probably will have to use local import because of circular imports -> remove
from pages.main_page import MainPage

from login_page.py and import it inside the age_gender_verification:
def age_gender_verification(self): from pages.main_page import MainPage
and if I were you I would try to avoid * imports
Reply
#5
It works at first but I think the inheritance gets all messed up because there is a BasePage class within MainPage and LoginPage after reusing a function which is in BasePage I get this error. Strangely only the BasePage function doesnt work and the MainPage class still does.

I updated the code in the post before that.

Error:
Error Traceback (most recent call last): File "C:\Python\Python38-32\lib\unittest\case.py", line 60, in testPartExecutor yield File "C:\Python\Python38-32\lib\unittest\case.py", line 676, in run self._callTestMethod(testMethod) File "C:\Python\Python38-32\lib\unittest\case.py", line 633, in _callTestMethod method() File "C:\MEGA\Private_Project\POM\tests\test_sign_in_page.py", line 11, in test_sign_in_with_in_valid_user result = login_page.login() File "C:\MEGA\Private_Project\POM\pages\login_page.py", line 44, in login self.age_gender_verification() File "C:\MEGA\Private_Project\POM\pages\login_page.py", line 74, in age_gender_verification MainPage(self).login_click() File "C:\MEGA\Private_Project\POM\pages\main_page.py", line 35, in login_click self.switch_to_login_iframe() File "C:\MEGA\Private_Project\POM\pages\main_page.py", line 31, in switch_to_login_iframe self.switch_iframe(self.iframe) File "C:\MEGA\Private_Project\POM\pages\base_page.py", line 46, in switch_iframe self.driver.switch_to.frame(element) AttributeError: 'LoginPage' object has no attribute 'switch_to'
base_page.py
import time from selenium.webdriver.common.action_chains import ActionChains from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.common.exceptions import TimeoutException,NoSuchElementException # this Base class is serving basic attributes for every single page inherited from Page class from utils import users class BasePage(object): def __init__(self, driver, base_url='https://soundcloud.com/'): print("base_page __init__") self.base_url = base_url self.driver = driver #self.driver.get(base_url) def find_element(self, *locator): self.wait_element(locator) return self.driver.find_element(*locator) def check_element(self, *locator): time.sleep(1) try: return self.driver.find_element(*locator) except NoSuchElementException: return False def open(self, url): url = self.base_url + url self.driver.get(url) def get_title(self): return self.driver.title def get_url(self): return self.driver.current_url def hover(self, *locator): element = self.find_element(*locator) hover = ActionChains(self.driver).move_to_element(element) hover.perform() def switch_iframe(self, element): self.driver.switch_to.frame(element) def switch_window(self, x): self.driver.switch_to.window(self.driver.window_handles[x]) def wait_element(self, *locator): try: WebDriverWait(self.driver, 10).until(EC.presence_of_element_located(*locator)) except TimeoutException: print("\n * ELEMENT NOT FOUND WITHIN GIVEN TIME! --> %s" %(locator[1])) self.driver.quit()
Maybe the POM model I am using is wrong or am I doing something wrong?
my problem is that after intialising MainPage which clicks the login button and returns LoginPage which trys to login with email and password I sometimes need to restart the login process from the LoginPage class function and use the MainPage login click function again but this POM model from github: https://github.com/gunesmes/page-object-...-selenium/ doesnt really seem to allow it because I cant somehow easily jump between the classes with the same objects and functions.
Reply
#6
I don't understand this line:
MainPage(self).login_click()
and it seems to be the problem, as you are initializing MainPage instance and passing it an instance of LoginPage instead of a driver.

But from a quick overall look, it feels like going this direction you will have more problems, as you are trying to restart the login process from inside the LoginPage instance by creating another LoginPage instance.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Click on a button on web page using Selenium Pavel_47 7 8,676 Jan-05-2023, 04:20 AM
Last Post: ellapurnellrt
  Selenium/Helium loads up a blank web page firaki12345 0 3,318 Mar-23-2021, 11:51 AM
Last Post: firaki12345
  Saving html page and reloading into selenium while developing all xpaths Larz60+ 4 7,033 Feb-04-2021, 07:01 AM
Last Post: jonathanwhite1
  Selenium Parsing (unable to Parse page after loading) oneclick 7 8,765 Oct-30-2020, 08:13 PM
Last Post: tomalex
  Code example for entering input in a textbox with requests/selenium object peterjv26 1 3,585 Sep-26-2020, 04:34 PM
Last Post: Larz60+
  Selenium on Angular page Martinelli 3 8,720 Jul-28-2020, 12:40 PM
Last Post: Martinelli
  use Xpath in Python :: libxml2 for a page-to-page skip-setting apollo 2 5,899 Mar-19-2020, 06:13 PM
Last Post: apollo
  Selenium get data from newly accessed page hoff1022 2 4,263 Oct-09-2019, 06:52 PM
Last Post: hoff1022
  Difficult web page -- Selenium Larz60+ 2 3,897 Dec-31-2018, 06:51 PM
Last Post: Larz60+
  Web Page not opening while web scraping through python selenium sumandas89 4 14,061 Nov-19-2018, 02:47 PM
Last Post: snippsat

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020
This forum uses Lukasz Tkacz MyBB addons.
Forum use Krzysztof "Supryk" Supryczynski addons.