Search code examples
pythonseleniumpageobjects

How does the page.py file and the element.py file interact on the Selenium PageObject tutorial? What is the BasePageElement?


Based on user input on a search engine, I am trying to scrape data from the search results on a website through multiple layers. The search results of the user may vary so I decided to use the PageObject design pattern to scale my project, but I don't understand the Python Selenium tutorial and how the element.py file and page.py file interact so I can edit them to my liking.

I am following this tutorial: https://selenium-python.readthedocs.io/page-objects.html

What is the BasePageElement? Is this file only apply to the first layer for webscraping? Should I copy the BasePageElement class and edit it for the next layer in my webscraping journey into a website? Is there a better explanation on what the element.py file is actually doing?


Solution

  • Example for page Stackoveflow

    But current classes have two problems for me:

    • BasePageElement uses only find_element_by_name and it is useless to search elements different then fields in form.

    • BasePageElement search on single element so it is useless to get all results on search page.

    It would need other classes to make it more useful.

    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.common.exceptions import NoSuchElementException, TimeoutException
    
    # --- original classes ---
    
    class BasePage(object):
        """Base class to initialize the base page that will be called from all pages"""
    
        def __init__(self, driver):
            self.driver = driver
    
    class BasePageElement(object):
        """Base page class that is initialized on every page object class."""
    
        def __set__(self, obj, value):
            """Sets the text to the value supplied"""
            driver = obj.driver
    
            WebDriverWait(driver, 100).until(
                lambda driver: driver.find_element_by_name(self.locator))
            driver.find_element_by_name(self.locator).clear()
            driver.find_element_by_name(self.locator).send_keys(value)
            #driver.find_element_by_name(self.locator).send_keys(Keys.Return)
    
        def __get__(self, obj, owner):
            """Gets the text of the specified object"""
            driver = obj.driver
            WebDriverWait(driver, 100).until(
                lambda driver: driver.find_element_by_name(self.locator))
            element = driver.find_element_by_name(self.locator)
            return element.get_attribute("value")
    
    # --- my classes ---
    
    class SearchTextElement(BasePageElement):
    
        locator = 'q'
    
    class MainPage(BasePage):
    
        # element has to be defined here 
        # (not as `self.field` because it will not work as expected)
        search_text_element = SearchTextElement()
    
        def search(self, query):
            self.search_text_element = [query, Keys.RETURN]
    
    # ---- 
    
    class ResultElement(BasePageElement):
    
        locator = 'q' # there is no other `name` on Stackoveflow
    
    class ResultPage(BasePage):
    
        # element has to be defined here 
        # (not as `self.field` because it will not work as expected)
        result_element = ResultElement()
    
        def get_result(self):
            return self.result_element
    
    # --- main ---
    
    #driver = webdriver.Firefox()
    driver = webdriver.Chrome()
    driver.get('https://stackoverflow.com')
    
    main_page = MainPage(driver)
    main_page.search('selenium')
    
    result_page = ResultPage(driver)
    result = result_page.get_result()
    print('result:', result)