Сторінка Object Model & Factory в Selenium
Що таке об’єктна модель сторінки?
Об'єктна модель сторінки (POM) це шаблон дизайну, який широко використовується в автоматизації тестування, який створює репозиторій об’єктів для елементів веб-інтерфейсу користувача. Перевагою моделі є те, що вона зменшує дублювання коду та покращує обслуговування тестів.
За цією моделлю для кожної веб-сторінки в додатку має бути відповідний клас сторінки. Цей клас Page ідентифікує WebElements цієї веб-сторінки, а також містить методи Page, які виконують операції над цими WebElements. Назви цих методів слід надавати відповідно до завдання, яке вони виконують, тобто, якщо завантажувач чекає появи платіжного шлюзу, ім’я методу POM може бути waitForPaymentScreenDisplay().
Чому об’єктна модель сторінки?
Запуск автоматизації інтерфейсу користувача в Selenium WebDriver НЕ складне завдання. Потрібно просто знайти елементи, виконати над ними операції.
Розгляньте цей простий скрипт для входу на веб-сайт
Як ви бачите, усе, що ми робимо, це знаходимо елементи та заповнюємо значення для цих елементів.
Це невеликий сценарій. Обслуговування сценарію виглядає легко. Але з часом набір тестів буде розширюватися. Коли ви додаєте все більше і більше рядків до свого коду, все стає складніше.
Основна проблема з підтримкою сценаріїв полягає в тому, що якщо 10 різних сценаріїв використовують той самий елемент сторінки, при будь-якій зміні в цьому елементі вам потрібно змінити всі 10 сценаріїв. Це займає багато часу та може викликати помилки.
Кращий підхід до обслуговування сценаріїв полягає у створенні окремого файлу класу, який би знаходив веб-елементи, заповнював їх або перевіряв їх. Цей клас можна повторно використовувати в усіх сценаріях, які використовують цей елемент. У майбутньому, якщо буде змінено веб-елемент, нам потрібно буде внести зміни лише в 1 файл класу, а не в 10 різних сценаріях.
Цей підхід називається Page Object Model in Selenium. Це допомагає зробити код більш читабельним, зручним для обслуговування та повторним використанням.
Переваги ПОМ
- Шаблон дизайну об’єкта сторінки каже, що операції та потоки в інтерфейсі користувача мають бути відокремлені від перевірки. Ця концепція робить наш код чистішим і зрозумілішим.
- Друга перевага полягає в тому, що репозиторій об’єктів не залежить від тестових випадків, тому ми можемо використовувати той самий репозиторій об’єктів для різних цілей з різними інструментами. Наприклад, ми можемо інтегрувати об’єктну модель сторінки Selenium з TestNG/JUnit для функціональних Тестування і в той же час з JBehave/Cucumber для приймальних випробувань.
- Код стає меншим і оптимізованим через багаторазово використовувані методи сторінок у класах POM.
- Методи отримують більш реалістичні назви, які можна легко зіставити з операціями, що відбуваються в інтерфейсі користувача. тобто якщо після натискання кнопки ми потрапляємо на домашню сторінку, назва методу буде схожою на 'gotoHomePage()'.
Як реалізувати POM?
Простий POM:
Це базова структура структури об’єктної моделі сторінки, де всі веб-елементи AUT і метод, який працює з цими веб-елементами, зберігається у файлі класу. Таке завдання, як перевірка, має бути окремою частиною методів тестування.
Повний приклад
TestCase: Перейдіть на демонстраційний сайт 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("https://demo.guru99.com/V4/"); } /** * This test case will login in https://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")); }
У чому полягає Page Factory Selenium?
Page Factory в Selenium це вбудована концепція каркаса об’єктної моделі сторінки для Selenium WebDriver, але він дуже оптимізований. Він використовується для ініціалізації об’єктів Page або для створення екземпляра самого об’єкта Page. Він також використовується для ініціалізації елементів класу Page без використання «FindElement/s».
Тут також ми дотримуємося концепції поділу сховища об’єктів сторінки та методів тестування. Крім того, за допомогою класу PageFactory в Selenium, використовуємо анотації @FindBy щоб знайти WebElement. Ми використовуємо метод initElements для ініціалізації веб-елементів
@FindBy може прийняти tagName, partialLinkText, name, linkText, id, css, className, 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 із 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 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("https://demo.guru99.com/V4/"); } /** * This test go to https://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 об’єктна модель сторінки створює наш тестовий код, який можна підтримувати та використовувати повторно.
- Page Factory — це оптимізований спосіб створення репозиторію об’єктів у рамках концепції Page Object Model.
- AjaxElementLocatorFactory — це концепція відкладеного завантаження у Page Factory — шаблон дизайну об’єкта сторінки для ідентифікації WebElements лише тоді, коли вони використовуються в будь-якій операції.
Завантажити Selenium Файли проекту для демонстрації в цьому посібнику