Объектная модель страницы (POM) и фабрика страниц в Selenium
Что такое объектная модель страницы?
Объектная модель страницы (POM) — это шаблон проектирования, широко используемый в автоматизации тестирования, который создает репозиторий объектов для элементов веб-интерфейса. Преимущество модели в том, что она уменьшает дублирование кода и улучшает обслуживание тестов.
Согласно этой модели, для каждой веб-страницы в приложении должен существовать соответствующий класс страницы. Этот класс Page будет идентифицировать WebElements этой веб-страницы, а также содержит методы Page, которые выполняют операции с этими WebElements. Имя этих методов должно быть указано в соответствии с задачей, которую они выполняют, т.е. если загрузчик ожидает появления платежного шлюза, имя метода POM может быть waitForPaymentScreenDisplay().
Почему объектная модель страницы?
Запуск автоматизации пользовательского интерфейса в Selenium WebDriver — НЕ сложная задача. Вам просто нужно находить элементы, выполнять над ними операции.
Рассмотрим этот простой сценарий для входа на веб-сайт.
Как вы можете заметить, все, что мы делаем, — это находим элементы и заполняем значения для этих элементов.
Это небольшой сценарий. Обслуживание скриптов выглядит простым. Но со временем набор тестов будет расширяться. По мере того, как вы добавляете в код все больше и больше строк, все становится сложнее.
Основная проблема с обслуживанием скриптов заключается в том, что если 10 разных скриптов используют один и тот же элемент страницы, то при любом изменении этого элемента вам придется изменить все 10 скриптов. Это отнимает много времени и чревато ошибками.
Лучшим подходом к обслуживанию скриптов является создание отдельного файла класса, который будет находить веб-элементы, заполнять их или проверять. Этот класс можно повторно использовать во всех сценариях, использующих этот элемент. В будущем, если в веб-элементе произойдут изменения, нам нужно будет внести изменения всего в 1 файл класса, а не в 10 разных скриптов.
Этот подход называется объектной моделью страницы. Selenium. Это помогает сделать код более читабельным, поддерживаемым и пригодным для повторного использования.
Преимущества ПОМ
- Шаблон проектирования объектов страницы говорит, что операции и потоки в пользовательском интерфейсе должны быть отделены от проверки. Эта концепция делает наш код чище и понятнее.
- Второе преимущество заключается в том, что репозиторий объектов не зависит от тестовых случаев, поэтому мы можем использовать один и тот же репозиторий объектов для разных целей с разными инструментами. Например, мы можем интегрировать объектную модель страницы в Selenium TestNG/JUnit для функционального Тестирование и в то же время с JBehave/Cucumber для приемочных испытаний.
- Код становится меньше и оптимизирован благодаря многоразовым методам страниц в классах POM.
- Методы получают более реалистичные имена, которые можно легко сопоставить с операциями, происходящими в пользовательском интерфейсе. т.е. если после нажатия кнопки мы попадаем на домашнюю страницу, имя метода будет выглядеть как «gotoHomePage()».
Как реализовать ПОМ?
Простой ПОМ:
Это базовая структура объектной модели страницы, в которой все веб-элементы AUT и метод, который работает с этими веб-элементами, хранится внутри файла класса. Такая задача, как проверка, должна быть отдельной как часть методов тестирования.
Полный пример
Прецедент: Перейдите на демонстрационный сайт Guru99.
Шаг 1) Перейдите на демонстрационный сайт Guru99.
Шаг 2) На главной странице проверьте текст «Guru99 Bank».
Шаг 3) Войдите в приложение
Шаг 4) Убедитесь, что на домашней странице содержится текст «Идентификатор менеджера: демо».
Здесь мы имеем дело с 2 страницами
- Страница входа
- Домашняя страница (отображается после входа в систему)
Соответственно создаем 2 POM в Selenium классов
Guru99 Страница входа POM
package pages; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; public class Guru99Login { WebDriver driver; By user99GuruName = By.name("uid"); By password99Guru = By.name("password"); By titleText =By.className("barone"); By login = By.name("btnLogin"); public Guru99Login(WebDriver driver){ this.driver = driver; } //Set user name in textbox public void setUserName(String strUserName){ driver.findElement(user99GuruName).sendKeys(strUserName); } //Set password in password textbox public void setPassword(String strPassword){ driver.findElement(password99Guru).sendKeys(strPassword); } //Click on login button public void clickLogin(){ driver.findElement(login).click(); } //Get the title of Login Page public String getLoginTitle(){ return driver.findElement(titleText).getText(); } /** * This POM method will be exposed in test case to login in the application * @param strUserName * @param strPasword * @return */ public void loginToGuru99(String strUserName,String strPasword){ //Fill user name this.setUserName(strUserName); //Fill password this.setPassword(strPasword); //Click Login button this.clickLogin(); } }
Домашняя страница Guru99 POM в Selenium
package pages; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; public class Guru99HomePage { WebDriver driver; By homePageUserName = By.xpath("//table//tr[@class='heading3']"); public Guru99HomePage(WebDriver driver){ this.driver = driver; } //Get the User name from Home Page public String getHomePageDashboardUserName(){ return driver.findElement(homePageUserName).getText(); } }
Guru99 Простой POM в Selenium Прецедент
package test; import java.util.concurrent.TimeUnit; import org.openqa.selenium.WebDriver; import org.openqa.selenium.firefox.FirefoxDriver; import org.testng.Assert; import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; import pages.Guru99HomePage; import pages.Guru99Login; public class Test99GuruLogin { String driverPath = "C:\\geckodriver.exe"; WebDriver driver; Guru99Login objLogin; Guru99HomePage objHomePage; @BeforeTest public void setup(){ System.setProperty("webdriver.gecko.driver", driverPath); driver = new FirefoxDriver(); driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS); driver.get("http://demo.guru99.com/V4/"); } /** * This test case will login in http://demo.guru99.com/V4/ * Verify login page title as guru99 bank * Login to application * Verify the home page using Dashboard message */ @Test(priority=0) public void test_Home_Page_Appear_Correct(){ //Create Login Page object objLogin = new Guru99Login(driver); //Verify login page title String loginPageTitle = objLogin.getLoginTitle(); Assert.assertTrue(loginPageTitle.toLowerCase().contains("guru99 bank")); //login to application objLogin.loginToGuru99("mgr123", "mgr!23"); // go the next page objHomePage = new Guru99HomePage(driver); //Verify home page Assert.assertTrue(objHomePage.getHomePageDashboardUserName().toLowerCase().contains("manger id : mgr123")); }
Что такое Фабрика страниц? Selenium?
Фабрика страниц в Selenium — это встроенная концепция структуры объектной модели страницы для Selenium WebDriver, но он очень оптимизирован. Он используется для инициализации объектов Page или для создания экземпляра самого объекта Page. Он также используется для инициализации элементов класса Page без использования «FindElement/s».
Здесь мы также следуем концепции разделения репозитория объектов страницы и методов тестирования. Кроме того, с помощью класса PageFactory в Selenium, мы используем аннотации @FindBy чтобы найти ВебЭлемент. Мы используем метод initElements для инициализации веб-элементов.
@FindBy могу принять имя тега, частичный текст ссылки, имя, текст ссылки, идентификатор, CSS, имя класса, xpath как атрибуты.
Давайте посмотрим на тот же пример, что и выше, с использованием Page Factory.
Страница входа Guru99 с Page Factory
package PageFactory; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.support.FindBy; import org.openqa.selenium.support.PageFactory; public class Guru99Login { /** * All WebElements are identified by @FindBy annotation */ WebDriver driver; @FindBy(name="uid") WebElement user99GuruName; @FindBy(name="password") WebElement password99Guru; @FindBy(className="barone") WebElement titleText; @FindBy(name="btnLogin") WebElement login; public Guru99Login(WebDriver driver){ this.driver = driver; //This initElements method will create all WebElements PageFactory.initElements(driver, this); } //Set user name in textbox public void setUserName(String strUserName){ user99GuruName.sendKeys(strUserName); } //Set password in password textbox public void setPassword(String strPassword){ password99Guru.sendKeys(strPassword); } //Click on login button public void clickLogin(){ login.click(); } //Get the title of Login Page public String getLoginTitle(){ return titleText.getText(); } /** * This POM method will be exposed in test case to login in the application * @param strUserName * @param strPasword * @return */ public void loginToGuru99(String strUserName,String strPasword){ //Fill user name this.setUserName(strUserName); //Fill password this.setPassword(strPasword); //Click Login button this.clickLogin(); } }
Домашняя страница Guru99 с фабрикой страниц
package PageFactory; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.support.FindBy; import org.openqa.selenium.support.PageFactory; public class Guru99HomePage { WebDriver driver; @FindBy(xpath="//table//tr[@class='heading3']") WebElement homePageUserName; public Guru99HomePage(WebDriver driver){ this.driver = driver; //This initElements method will create all WebElements PageFactory.initElements(driver, this); } //Get the User name from Home Page public String getHomePageDashboardUserName(){ return homePageUserName.getText(); } }
Guru99 TestCase с концепцией Page Factory
package test; import java.util.concurrent.TimeUnit; import org.openqa.selenium.WebDriver; import org.openqa.selenium.firefox.FirefoxDriver; import org.testng.Assert; import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; import PageFactory.Guru99HomePage; import PageFactory.Guru99Login; public class Test99GuruLoginWithPageFactory { String driverPath = "C:\\geckodriver.exe"; WebDriver driver; Guru99Login objLogin; Guru99HomePage objHomePage; @BeforeTest public void setup(){ System.setProperty("webdriver.gecko.driver", driverPath); driver = new FirefoxDriver(); driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS); driver.get("http://demo.guru99.com/V4/"); } /** * This test go to http://demo.guru99.com/V4/ * Verify login page title as guru99 bank * Login to application * Verify the home page using Dashboard message */ @Test(priority=0) public void test_Home_Page_Appear_Correct(){ //Create Login Page object objLogin = new Guru99Login(driver); //Verify login page title String loginPageTitle = objLogin.getLoginTitle(); Assert.assertTrue(loginPageTitle.toLowerCase().contains("guru99 bank")); //login to application objLogin.loginToGuru99("mgr123", "mgr!23"); // go the next page objHomePage = new Guru99HomePage(driver); //Verify home page Assert.assertTrue(objHomePage.getHomePageDashboardUserName().toLowerCase().contains("manger id : mgr123")); } }
Полная структура проекта будет выглядеть так:
AjaxElementLocatorFactory
AjaxElementLocatorFactory — это концепция отложенной загрузки PageFactory в Selenium. Он используется для поиска веб-элементов только тогда, когда элементы используются в какой-либо операции. Он назначает тайм-аут для WebElements классу страницы объекта. Одно из ключевых преимуществ использования шаблона PageFactory в Selenium — это класс AjaxElementLocatorFactory.
Здесь при выполнении операции над элементом ожидание его видимости начинается только с этого момента. Если элемент не найден за заданный интервал времени, Тестовый кейс выполнение выдаст исключение NoSuchElementException.
Итого
- Объектная модель страницы в Selenium WebDriver — это шаблон проектирования репозитория объектов.
- Selenium Объектная модель страницы делает наш тестовый код удобным в обслуживании и пригодным для повторного использования.
- Фабрика страниц — это оптимизированный способ создания репозитория объектов в концепции платформы объектной модели страницы.
- AjaxElementLocatorFactory — это концепция отложенной загрузки в Page Factory — шаблон проектирования объектов страницы, позволяющий идентифицировать веб-элементы только тогда, когда они используются в какой-либо операции.
Скачать Selenium Файлы проекта для демонстрации в этом руководстве