Skip to content

Selenium и Page Object паттерн

Page Object – один из наиболее полезных и используемых архитектурных решений в автоматизации. Данный паттерн помогает вынести элементы отдельных страниц в отдельные классы, отвечающие за работу с HTML каждой конкретной веб-страницы.

Такой подход значительно уменьшает объем повторяющегося кода, потому что одни и те же объекты страниц можно использовать в различных тестах.

Основное преимущество заключается в том, что в случае изменения пользовательского интерфейса, можно выполнить исправление только в одном месте, а не исправлять каждый тест, в котором этот интерфейс используется.

Дальше покажу пример использования, выполнив рефакторинг наших автотестов по сайту Wikipedia.

Начнем с того, что в каждом тесте мы переходим по URL сайта Wikipedia и выполняем поиск:

Как мы видим у нас дублируется код и локаторы при поиске элементов, а это не очень хорошо, поскольку в случае, когда измениться локатор к какому-либо элементу на этой странице, придется обновлять все тесты.

Чтобы решить эту проблему используем Page obgect паттерн.

  • Создадим класс SearchPage.cs с конструктором, который будет принимать экзепляр нашего драйвера для того чтобы мы работали в рамках одной сессии.
  • Перенесем в него поиск нужных нам элементов
    public class SearchPage
    {
        private IWebDriver _driver;
        public SearchPage(IWebDriver driver)
        {
            _driver = driver;
        }

        private IWebElement SearchField => _driver.FindElement(By.Id("searchInput"));
        private IWebElement SearchButton => _driver.FindElement(By.XPath("//i[text()='Search']"));

        public void Search(string query)
        {
            SearchField.SendKeys(query);
            SearchButton.Click();
        }
    }

Дальше в тестах мы можем создавать экземпляр класса данной страницы, предавать туда экземпляр драйвера и вызывать метод Search.

Для удобства, чтобы в тесте не создавать экземпляр класса SearchPage, мы можем в базовом для всех тестов классе BaseTest написать метод, который будет выполнять переход на страницу поиска

    public SearchPage OpenSearchPage()
    {
        driver.Navigate().GoToUrl(ConfigurationManager.AppSettings["URL"]);
        return new SearchPage(driver);
    }

Обновив тест в соответствии с созданным объектом страницы SearchPage тест будет выглядеть следующим образом:

На этом мы не останавливаемся и понимаем, что в обоих тестах после поиска открывается страница результатов (хоть и с разным содержанием, но с общими элементами).

Поэтому создадим класс результирующей страницы SearchResultsPage.cs с конструктором принимающим экзепляр драйвера и добавим в него поиск элемента “заглавие”

    public class SearchResultsPage
    {
        private IWebDriver _driver;
        public SearchResultsPage(IWebDriver driver)
        {
            _driver = driver;
        }
        public IWebElement PageHeader => _driver.FindElement(By.Id("firstHeading"));
    }

Теперь нам нужно обновить метод Search в классе SearchPage.cs таким образом, чтобы он нам возвращал экземпляр класса SearchResultsPage.cs

    public SearchResultsPage Search(string query)
    {
        SearchField.SendKeys(query);
        SearchButton.Click();
        return new SearchResultsPage(_driver);
    }

И обновим наши тесты таким образом, чтобы мы работали с объектами наших страниц:

Как результат мы видим, что наши тесты стали компактными и более читабельными за счет работы с объектами страниц. Ну и поддерживать такие тесты проще, поскольку наши элементы инкапсулированы в рамках классов и не дублируются в каждом тесте. 

Leave a Reply

Your email address will not be published. Required fields are marked *