t.me/atinfo_chat Telegram группа по автоматизации тестирования

Вопросы по некоторым моментам в Page Object

design-patterns
locators
page-factory
best-practices
page-object
python
webdriver
Теги: #<Tag:0x00007fb2f71a7320> #<Tag:0x00007fb2f71a71e0> #<Tag:0x00007fb2f71a70a0> #<Tag:0x00007fb2f71a6f60> #<Tag:0x00007fb2f71a6dd0> #<Tag:0x00007fb2f71a6c68> #<Tag:0x00007fb2f71a6b28>

(Артём Кузьменко) #1

Здравствуйте. Организовываю тесты с помощью Page Object на Python. В принципе разобрался, но есть несколько вопросов.
Есть 3 сущности: локаторы, страницы, тесты.
Страницы наследую от базовой страницы.
В страницах описываю действия на страницах - ввести данные в поле, нажать кнопку и т.п. Локаторы беру с модуля локаторов. В тестах используем объект страницы и дергаем методы.

Но вот вопросы:

  1. Получается, что у меня слишком много методов отдельных типа (input_name, click_login_btn) и писать в других тестах отдельными методами набор действий не очень хорошо. Как вы это делаете? Создаете методы которые группируют действия, типа login, а в нем уже группируете отдельные действия? И где эти сгруппированные методы писать? Тоже в этой же странице?
  2. Каким способом используете проверки. Тоже делаете методы которые возвращают текст элемента например? Или делаете это через @property? Т.е. если в тесте надо проверить, что на странице присутствует такой то текст или есть такой то элемент, то как организовываете такое в коде?
  3. Есть сущность группы. Перед тестами надо создать группу. Как это лучше сделать? Сделать отдельный класс, в котором сделать операции с группами или просто создавать объект типа старница группы и дергать его методы?

Вопросы больше по реализации сущностей в коде и удобном их использовании?

Пример страницы

class LoginPage(BasePage):

    login_page_loc = LoginPageLocators()

    def country_cmb_click(self):
        country_cmb = self.wait.element_to_be_clickable(*self.login_page_loc.COUNTRY_CMB)
        country_cmb.click()


    def search_country(self, country):
        country_search = self.wait.element_to_be_clickable(*self.login_page_loc.COUNTRY_SEARCH_INPUT)
        country_search.clear()
        country_search.send_keys(country)


    def country_item_click(self):
        country_item = self.wait.element_to_be_clickable(*self.login_page_loc.COUNTRY_ITEM)
        country_item.click()
        sleep(1)


    def country_popup_close(self):
        country_item = self.wait.element_to_be_clickable(*self.login_page_loc.COUNTRY_CLOSE_BTN)
        country_item.click()
        sleep(1)


    def get_country_name(self):
        return self.wait.element_to_be_clickable(*self.login_page_loc.COUNTRY_CMB).text


    def get_country_code(self):
        return self.wait.element_to_be_clickable(*self.login_page_loc.COUNTRY_CODE).text


    def get_invalid_numder_text(self):
        return self.wait.element_to_be_clickable(*self.login_page_loc.LOGIN_ERROR_MESSAGE).text


    def input_phone(self, phone):
        phone_input = self.driver.find_element(*self.login_page_loc.PHONE_INPUT)
        phone_input.clear()
        if phone.find('+7') != -1:
            phone = phone[2:]
        phone_input.send_keys(phone)


    def send_code_btn_click(self):
        send_code_btn = self.driver.find_element(*self.login_page_loc.SEND_CODE_BTN)
        send_code_btn.click()


    def resend_code_link_click(self):
        resend_code_link = self.wait.element_to_be_clickable(*self.login_page_loc.RESEND_CODE_LINK)
        resend_code_link.click()


    def get_resend_code_message(self):
        return self.wait.element_to_be_clickable(*self.login_page_loc.RESEND_CODE_MESSAGE).text


    def input_code(self, code):
        code_input = self.wait.element_to_be_clickable(*self.login_page_loc.CODE_INPUT)
        code_input.clear()
        code_input.send_keys(code)


    def login_btn_click(self):
        login_btn = self.wait.element_to_be_clickable(*self.login_page_loc.LOGIN_BTN)
        login_btn.click()
        return UserProfilePage(self.driver)

Пример тестов

class TestsLogin:
    config = read_yaml(os.path.join(const.PROJECT, 'config.yaml'))

    driver: webdriver
    driver = None

    web = config['web']
    user = config['users']['user1']
    phone = user['phone']
    code = user['code']

    def setup_class(self):
        self.driver = config_and_run_browser(self.web)

    def teardown_class(self):
        self.driver.close()


    @pytest.mark.positive
    def test1_change_country(self):
        login_page = LoginPage(self.driver)
        login_page.go_to_main_page()
        country = 'Angola'
        code = '+244'
        login_page.country_cmb_click()
        login_page.search_country(country)
        login_page.country_item_click()
        assert country == login_page.get_country_name()
        assert code == login_page.get_country_code()


    @pytest.mark.positive
    def test2_change_country_close_popup(self):
        login_page = LoginPage(self.driver)
        login_page.go_to_main_page()
        country = login_page.get_country_name()
        code = login_page.get_country_code()
        login_page.country_cmb_click()
        login_page.search_country(country)
        login_page.country_popup_close()
        assert country == login_page.get_country_name()
        assert code == login_page.get_country_code()


    @pytest.mark.negative
    def test3_input_invalid_number(self):
        login_page = LoginPage(self.driver)
        login_page.go_to_main_page()
        country = 'Russia'
        phone = '123'
        login_page.country_cmb_click()
        login_page.search_country(country)
        login_page.country_item_click()
        login_page.input_phone(phone)
        login_page.send_code_btn_click()
        assert 'Некорректный номер телефона' == login_page.get_invalid_numder_text()


    @pytest.mark.positive
    def test4_resend_code(self):
        login_page = LoginPage(self.driver)
        login_page.go_to_main_page()
        country = 'Russia'
        phone = self.phone
        login_page.country_cmb_click()
        login_page.search_country(country)
        login_page.country_item_click()
        login_page.input_phone(phone)
        login_page.send_code_btn_click()
        login_page.resend_code_link_click()
        assert 'Повторный запрос кода возможен через' in login_page.get_resend_code_message()


    @pytest.mark.positive
    def test5_input_valid_number_back_prev_page(self):
        login_page = LoginPage(self.driver)
        login_page.go_to_main_page()
        country = 'Russia'
        phone = self.phone
        code = self.code
        login_page.country_cmb_click()
        login_page.search_country(country)
        login_page.country_item_click()
        login_page.input_phone(phone)
        login_page.send_code_btn_click()
        login_page.input_code(code)
        user_profile_page = login_page.login_btn_click()
        firstname = 'Селен'
        lastname = 'Автотестов'
        user_profile_page.input_firstname(firstname)
        user_profile_page.input_lastname(lastname)
        team_profile_page = user_profile_page.create_team_btn_click()
        team_name = 'Dream Team'
        team_profile_page.input_name(team_name)
        user_profile_page = team_profile_page.user_profile_link_click()
        assert 'Сперва, давайте познакомимся!' == user_profile_page.get_hello_text()