Python, selenium, Page Object. pytest fixture - корректная реализация фикстуры

python
selenium
webdriver
Теги: #<Tag:0x00007f3d456e9310> #<Tag:0x00007f3d456e8ff0> #<Tag:0x00007f3d456e8a50>

(Philip Kandyba) #1

Добрый день!

Изначально я не корректно создал фикстуру. Теперь она мешает мне корректно передавать драйвер в экземпляры классов.

По порядку.

conftest.py

@pytest.yield_fixture(params=browsers.keys())
def driver(request):
    browser = browsers[request.param]()
    # Тут я создаю ексзепляр класса и передаю ему драйвер.
    login_page = LoginPage(browser)
    login_page.open_page('https://client.triggmine.com.ua/login')
    yield login_page
    browser.quit()

LoginPage.py наследуется от базового класса Page. Здесь функции по работе со страницей логин.

class LoginPage(Page):
    def is_notification_from_email_field(self):
        return self.is_displayed(LoginPageLocators.NOTIFICATION_EMPTY_EMAIL_FIELD)

    def is_notification_from_password_field(self):
        return self.is_displayed(LoginPageLocators.NOTIFICATION_EMPTY_PASSWORD_FIELD)

Base.py - это базовый клас с инициализацей и методами для работы с элементами.

class Page:

    def __init__(self, driver):
        self.driver = driver
        driver.maximize_window()

    def find_element(self, locator):
        return self.driver.find_element(locator[0], locator[1])

test_suite.py - сам файл с тестом который принимает фикстуру driver из conftest.py

def test_empty_fields(driver):
    driver.click_login_button()
    assert driver.is_notification_from_email_field()
    assert driver.is_notification_from_password_field()

Проблема собственно в том что я уже в самой фикстуре создаю экземпляр класса Login page и передаю ей драйвер. Это в корне не верно. Так как это приводит к тому что я не могу делать экземпляры других класов с методами для работы со страницами. Есть же еще и другие классы, например SignupPage но я не создавать экземпляры класса и предать в них драйвер.

Например тест на логин:

def test_login_in(driver):
    driver.login_in('login', '123456')
    assert driver.is_h2_title()

Где метод login_In в классе логин, а is_h2_title метод класса SignupPage.

Как правильно реализовать фикстуру что бы не было таких проблем. Спасибо.


(Maxim Zaitsev) #2

Ну раз понятна проблема, то нужно ее решать:

Фикстура возвращает только экземпляр драйвера

@pytest.yield_fixture(params=browsers.keys())
def driver(request):
    browser = browsers[request.param]()    
    yield browser 
    browser.quit()

Инициализация страницы происходит в теле теста:

def test_login_in(driver):
    login_page = LoginPage(driver)
    login_page.login_in('login', '123456')
    assert driver.is_h2_title()

(Philip Kandyba) #3

Ошибка:
def test_login_in(driver):

  login = LoginPage(driver)

E TypeError: 'module' object is not callable


#4

@Philip_Kandyba


(Maxim Andryushchenkov) #6

Зачем вам yield фикстура для получения драйвера? Вы только этим уже себя ограничиваете. Вот моя из conftest.py:

@pytest.fixture()
def get_driver(request, config):
    browser = request.config.getoption('--browser')
    results_dir = path.join(getcwd(), 'results')

    if not path.exists(results_dir):
        makedirs(results_dir)

    log_path = path.join(results_dir, 'driver.log')
    drivers_dir = path.join(getcwd(), 'drivers')

    driver = None
    driver_name = dict(
        firefox='geckodriver',
        chrome='chromedriver'
    )[browser]
    driver_path = path.join(drivers_dir, driver_name)

    if browser == 'firefox':
        driver = webdriver.Firefox(executable_path=driver_path, log_path=log_path)
    elif browser == 'chrome':
        driver = webdriver.Chrome(executable_path=driver_path, service_log_path=log_path)

    print(popen(f'{driver_path} --version').read())

    driver.page_config = config['page_config']
    driver.locators = config['locators']
    driver.maximize_window()

    def close_driver():
        driver.quit()

    request.addfinalizer(close_driver)
    return driver

Где config это фикстура получения конфига, который аттачится к драйверу. Потом в тесте укажите фикстуру get_driver и получите то что вам надо.
Плюс можно создать стенд перехода сразу на нужную страницу:

@pytest.fixture()
def get_welcome_page(get_driver):
    from pages.welcome_page import WelcomePage
    page = WelcomePage(get_driver)
    page.navigate()
    return page