Наследование от класса дескрипторов

#python #class #selenium-webdriver #python-descriptors

Вопрос:

Как работает этот класс дескрипторов в руководстве Selenium?

 from selenium.webdriver.support.ui import WebDriverWait


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)

    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")
 

Я вижу, что SearchTextElement класс наследует от него:

 class SearchTextElement(BasePageElement):
    """This class gets the search text from the specified locator"""

    #The locator for search box where search string is entered
    locator = 'q'
 

Но у этого класса таинственным образом есть только одна строка, в которой объявляется ошибка локатора (которая, предположительно, поступает в self.locator переменную при __get__() вызове и __set__() вызывается).

Затем этот класс, в свою очередь, инициируется в MainPage классе для «объявления переменной, которая будет содержать полученный текст».:

 class MainPage(BasePage):
    """Home page action methods come here. I.e. Python.org"""

    # Declares a variable that will contain the retrieved text
    search_text_element = SearchTextElement()
 

Отмечается, что в предоставленном тестовом коде поиск может быть выполнен путем установки этой переменной в строку:

 main_page.search_text_element = "pycon"
main_page.click_go_button()
 

Обычно я бы использовал одну функцию поиска, например:

 from selenium import webdriver

driver = webdriver.Firefox()
driver.get("http://www.python.org")

def search(keyword):
    wait = WebDriverWait(driver, 100)
    search = wait.until(EC.presence_of_element_located((By.NAME, 'q')))
    search.send_keys(keyword)
    search.submit()
 

Then simply call (if this function is in the MainPage class) main_page.search("pycon") to trigger the search.

Questions

  1. Why is this approach not preferred when designing a Selenium
    Scraper App?
  2. Создание экземпляра SearchTextElement() волшебным образом дает нам переменную для хранения входного текста. Это, по-видимому, вызывает __set__ функцию для выполнения работы. Как его использовать в контексте получения некоторого значения от элемента в результатах поиска?
  3. В этом контексте хорошей практикой должно быть хранение всех локаторов в одном месте, locators.py чтобы код можно было легко переделать для использования на других веб — сайтах. В моей собственной функции поиска выше, (By.NAME, 'q') может быть легко сохранена как КОНСТАНТА в MainPageLocators классе locators.py в. Как следует подходить к исправлению SearchTextElement.locator , чтобы оно не было жестко закодировано, как в приведенном выше примере?