page object model with page factory selenium tutorial
Този задълбочен урок обяснява всичко за обектния модел на страницата (POM) с Pagefactory, използвайки примери. Можете също така да научите прилагането на POM в селен:
В този урок ще разберем как да създадем обектен модел на страница, използвайки подхода на Page Factory. Ще се съсредоточим върху:
- Фабричен клас
- Как да създадете основен POM с помощта на Page Factory Pattern
- Различни анотации, използвани в подхода на фабричните страници
Преди да видим какво е Pagefactory и как може да се използва заедно с обектния модел Page, нека разберем какво е Page Object Model, който е известен като POM.
=> Посетете тук, за да видите поредицата за обучение за селен за всички.
Какво ще научите:
- Какво представлява обектният модел на страницата (POM)?
- Какво е Pagefactory?
- POM Използване на Page Factory
- често задавани въпроси
- Заключение
Какво представлява обектният модел на страницата (POM)?
Теоретичните терминологии описват Модел на обект на страница като модел на дизайн, използван за изграждане на хранилище на обекти за уеб елементите, налични в тестваното приложение. Малко други го наричат като рамка за автоматизация на Selenium за даденото тествано приложение.
Това, което разбрах за термина Page Object Model обаче е:
# 1) Това е модел на проектиране, при който имате отделен файл с клас на Java, съответстващ на всеки екран или страница в приложението. Файлът на класа може да включва хранилището на обекти на елементите на потребителския интерфейс, както и методи.
# две) В случай, че на една страница има огромни уеб елементи, класът на хранилището на обекти за страница може да бъде отделен от класа, който включва методи за съответната страница.
Пример: Ако страницата Регистрация на акаунта има много полета за въвеждане, тогава може да има клас RegisterAccountObjects.java, който формира хранилището на обекти за елементите на потребителския интерфейс на страницата на регистъра на акаунтите.
Може да бъде създаден отделен файл на класа RegisterAccount.java, който разширява или наследява RegisterAccountObjects, който включва всички методи, извършващи различни действия на страницата.
# 3) Освен това под пакета може да има родов пакет с файл {roperties, тестови данни на Excel и общи методи.
Пример: DriverFactory, който може да се използва много лесно на всички страници в приложението
Разбиране на POM с пример
Проверете тук за да научите повече за POM.
По-долу е моментна снимка на уеб страницата:
Кликването върху всяка от тези връзки ще пренасочи потребителя към нова страница.
Ето моментната снимка на това как се изгражда структурата на проекта със Selenium, използвайки обектния модел Page, съответстващ на всяка страница в уебсайта. Всеки клас Java включва хранилище на обекти и методи за извършване на различни действия в рамките на страницата.
Освен това ще има друг JUNIT или TestNG или файл с клас на Java, извикващ повиквания към файлове на класове на тези страници.
Защо използваме обектния модел на страницата?
Съществува шум около използването на тази мощна рамка на Selenium, наречена POM или обектен модел на страница. Сега възниква въпросът „Защо да използвам POM?“.
Простият отговор на това е, че POM е комбинация от управлявани от данни, модулни и хибридни рамки. Това е подход за систематично организиране на скриптовете по такъв начин, че улеснява QA да поддържа кода без проблеми, а също така помага за предотвратяване на излишен или дублиран код.
Например, ако има промяна в стойността на локатора на определена страница, тогава е много лесно да се идентифицира и направи тази бърза промяна само в скрипта на съответната страница, без да се влияе на кода другаде.
Използваме концепцията за обект на страници в Selenium Webdriver поради следните причини:
- В този POM модел се създава хранилище на обекти. Той е независим от тестовите случаи и може да бъде използван повторно за различен проект.
- Конвенцията за именуване на методите е много лесна, разбираема и по-реалистична.
- Под обектния модел Page ние създаваме класове на страници, които могат да бъдат използвани повторно в друг проект.
- Обектният модел Page е лесен за разработената рамка поради своите няколко предимства.
- В този модел се създават отделни класове за различни страници на уеб приложение като страница за вход, начална страница, страница с подробности за служителя, страница за промяна на паролата и т.н.
- Ако има някаква промяна в който и да е елемент на уебсайт, тогава трябва да направим промени само в един клас, а не във всички класове.
- Проектираният скрипт е по-многократно използваем, четим и поддържаем в подхода на страничния обектен модел.
- Структурата на проекта е доста лесна и разбираема.
- Може да използва PageFactory в обектния модел на страницата, за да инициализира уеб елемента и да съхранява елементи в кеша.
- TestNG може да бъде интегриран и в подхода на Page Object Model.
Внедряване на прост POM в селен
# 1) Сценарий за автоматизиране
Сега ние автоматизираме дадения сценарий, използвайки Page Object Model.
Сценарият е обяснен по-долу:
Етап 1: Стартирайте сайта „https: //demo.vtiger.com“.
Стъпка 2: Въведете валидните идентификационни данни.
Стъпка 3: Влезте в сайта.
Стъпка 4: Проверете началната страница.
Стъпка 5: Излезте от сайта.
Стъпка 6: Затворете браузъра.
# 2) Селенови скриптове за горния сценарий в POM
Сега създаваме POM структурата в Eclipse, както е обяснено по-долу:
Етап 1: Създайте проект в Eclipse - POM базирана структура:
а) Създайте проект „Модел на обект на страница“.
б) Създайте 3 пакета по проекта.
- библиотека
- страници
- тестови случаи
Библиотека: Под това поставяме тези кодове, които трябва да бъдат извиквани отново и отново в нашите тестови случаи, като стартиране на браузър, екранни снимки и др. Потребителят може да добави още класове под него въз основа на нуждите на проекта.
Страници: По този начин се създават класове за всяка страница в уеб приложението и могат да добавят повече класове страници въз основа на броя страници в приложението.
Тестови случаи: Под това пишем тестовия случай за влизане и можем да добавим още тестови случаи, колкото е необходимо, за да тестваме цялото приложение.
в) Класовете под пакетите са показани на изображението по-долу.
Стъпка две: Създайте следните класове под пакета библиотека.
Browser.java: В този клас са дефинирани 3 браузъра (Firefox, Chrome и Internet Explorer) и той се извиква в тестовия случай за влизане. Въз основа на изискването потребителят може да тества приложението и в различни браузъри.
package library; import org.openqa.selenium.WebDriver; import org.openqa.selenium.chrome.ChromeDriver; import org.openqa.selenium.firefox.FirefoxDriver; import org.openqa.selenium.ie.InternetExplorerDriver; public class Browser { static WebDriver driver; public static WebDriver StartBrowser(String browsername , String url) { // If the browser is Firefox if (browsername.equalsIgnoreCase('Firefox')) { // Set the path for geckodriver.exe System.setProperty('webdriver.firefox.marionette',' E://Selenium//Selenium_Jars//geckodriver.exe '); driver = new FirefoxDriver(); } // If the browser is Chrome else if (browsername.equalsIgnoreCase('Chrome')) { // Set the path for chromedriver.exe System.setProperty('webdriver.chrome.driver','E://Selenium//Selenium_Jars//chromedriver.exe'); driver = new ChromeDriver(); } // If the browser is IE else if (browsername.equalsIgnoreCase('IE')) { // Set the path for IEdriver.exe System.setProperty('webdriver.ie.driver','E://Selenium//Selenium_Jars//IEDriverServer.exe'); driver = new InternetExplorerDriver(); } driver.manage().window().maximize(); driver.get(url); return driver; } }
ScreenShot.java: В този клас се пише програма за скрийншот и тя се извиква в тестовия случай, когато потребителят иска да направи екранна снимка дали тестът е неуспешен или преминал.
package library; import java.io.File; import org.apache.commons.io.FileUtils; import org.openqa.selenium.OutputType; import org.openqa.selenium.TakesScreenshot; import org.openqa.selenium.WebDriver; public class ScreenShot { public static void captureScreenShot(WebDriver driver, String ScreenShotName) { try { File screenshot=((TakesScreenshot)driver).getScreenshotAs(OutputType. FILE ); FileUtils.copyFile(screenshot, new File('E://Selenium//'+ScreenShotName+'.jpg')); } catch (Exception e) { System. out .println(e.getMessage()); e.printStackTrace(); } } }
Стъпка 3: Създайте класове на страници в пакета Page
HomePage.java: Това е класът Начална страница, в който са дефинирани всички елементи на началната страница и методи.
package pages; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; public class HomePage { WebDriver driver; By logout = By.id('p_lt_ctl03_wSOB_btnSignOutLink'); By home = By.id('p_lt_ctl02_wCU2_lblLabel'); //Constructor to initialize object public HomePage(WebDriver dr) { this .driver=dr; } public String pageverify() { return driver.findElement(home).getText(); } public void logout() { driver.findElement(logout).click(); } }
LoginPage.java: Това е класът на страницата за вход, в който са дефинирани всички елементи на страницата за вход и методи.
package pages; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; public class LoginPage { WebDriver driver; By UserID = By.xpath('//*(contains(@id,'Login1_UserName'))'); By password = By.xpath('//*(contains(@id,'Login1_Password'))'); By Submit = By.xpath('//*(contains(@id,'Login1_LoginButton'))'); //Constructor to initialize object public LoginPage(WebDriver driver) { this .driver = driver; } public void loginToSite(String Username, String Password) { this .enterUsername(Username); this .enterPasssword(Password); this .clickSubmit(); } public void enterUsername(String Username) { driver.findElement(UserID).sendKeys(Username); } public void enterPasssword(String Password) { driver.findElement(password).sendKeys(Password); } public void clickSubmit() { driver.findElement(Submit).click(); } }
Стъпка 4: Създайте тестови случаи за сценария за влизане.
LoginTestCase.java: Това е класът LoginTestCase, където се изпълнява тестовият случай. Потребителят може също да създаде повече тестови случаи според нуждите на проекта.
package testcases; import java.util.concurrent.TimeUnit; import library.Browser; import library.ScreenShot; import org.openqa.selenium.WebDriver; import org.testng.Assert; import org.testng.ITestResult; import org.testng.annotations.AfterMethod; import org.testng.annotations.AfterTest; import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; import pages.HomePage; import pages.LoginPage; public class LoginTestCase { WebDriver driver; LoginPage lp; HomePage hp; int i = 0; // Launch of the given browser. @BeforeTest public void browserlaunch() { driver = Browser.StartBrowser('Chrome', 'http://demostore.kenticolab.com/Special-Pages/Logon.aspx'); driver.manage().timeouts().implicitlyWait(30,TimeUnit. SECONDS ); lp = new LoginPage(driver); hp = new HomePage(driver); } // Login to the Site. @Test(priority = 1) public void Login() { lp.loginToSite('gaurav.3n@gmail.com','Test@123'); } // Verifing the Home Page. @Test(priority = 2) public void HomePageVerify() { String HomeText = hp.pageverify(); Assert.assertEquals(HomeText, 'Logged on as'); } // Logout the site. @Test(priority = 3) public void Logout() { hp.logout(); } // Taking Screen shot on test fail @AfterMethod public void screenshot(ITestResult result) { i = i+1; String name = 'ScreenShot'; String x = name+String.valueOf(i); if (ITestResult. FAILURE == result.getStatus()) { ScreenShot.captureScreenShot(driver, x); } } @AfterTest public void closeBrowser() { driver.close(); } }
Стъпка 5: Изпълнете „LoginTestCase.java“.
Стъпка 6: Изход на обектния модел на страницата:
- Стартирайте браузъра Chrome.
- Демонстрационният уебсайт се отваря в браузъра.
- Влезте в демонстрационния сайт.
- Проверете началната страница.
- Излезте от сайта.
- Затворете браузъра.
Сега, нека разгледаме основната концепция на този урок, която привлича вниманието, т.е. “Pagefactory”.
Какво е Pagefactory?
PageFactory е начин за прилагане на „Модел на обект на страница“. Тук следваме принципа на разделяне на Page Object Repository и тестовите методи. Това е вградена концепция за Page Object Model, която е много оптимизирана.
Нека сега имаме повече яснота относно термина Pagefactory.
# 1) Първо, концепцията, наречена Pagefactory, предоставя алтернативен начин от гледна точка на синтаксис и семантика за създаване на хранилище на обекти за уеб елементите на страница.
# две) На второ място, той използва малко по-различна стратегия за инициализация на уеб елементите.
# 3) Хранилището на обекти за уеб елементите на потребителския интерфейс може да бъде изградено с помощта на:
- Обикновено „POM без Pagefactory“ и,
- Като алтернатива можете да използвате „POM с Pagefactory“.
По-долу е дадено изобразително изображение на същото:
Сега ще разгледаме всички аспекти, които разграничават обичайния POM от POM с Pagefactory.
а) Разликата в синтаксиса на намиране на елемент, използвайки обичайния POM срещу POM с Pagefactory.
Например , Щракнете тук за да намерите полето за търсене, което се показва на страницата.
POM без Pagefactory:
# 1) По-долу е как намирате полето за търсене, използвайки обичайния POM:
WebElement searchNSETxt=driver.findElement(By.id(“searchBox”));
# 2) Следващата стъпка предава стойността „инвестиция“ в полето Search NSE.
searchNSETxt.sendkeys(“investment”);
POM Използване на Pagefactory:
# 1) Можете да намерите полето за търсене с помощта на Pagefactory, както е показано по-долу.
Анотацията @FindBy се използва в Pagefactory за идентифициране на елемент, докато POM без Pagefactory използва driver.findElement () метод за намиране на елемент.
Второто изявление за Pagefactory след @FindBy е присвояване на тип WebElement клас, който работи точно подобно на присвояването на име на елемент от тип WebElement клас като връщащ тип на метода driver.findElement () който се използва в обичайния POM (searchNSETxt в този пример).
Ще разгледаме @FindBy подробно пояснения в предстоящата част на този урок.
@FindBy(id = 'searchBox') WebElement searchNSETxt;
# две) Следващата стъпка предава стойността „инвестиция“ в полето Search NSE и синтаксисът остава същият като този на обичайния POM (POM без Pagefactory).
searchNSETxt.sendkeys(“investment”);
б) Разликата в стратегията за инициализация на уеб елементи, използвайки обичайните POM срещу POM с Pagefactory.
Използване на POM без Pagefactory:
По-долу е даден кодов фрагмент за задаване на пътя на драйвера на Chrome. Екземпляр на WebDriver се създава с името драйвер и ChromeDriver се присвоява на „драйвер“. След това същият обект на драйвер се използва за стартиране на уебсайта на Националната фондова борса, намиране на searchBox и въвеждане на стойността на низа в полето.
Въпросът, който бих искал да подчертая тук е, че когато е POM без фабрична страница, екземплярът на драйвера се създава първоначално и всеки уеб елемент се инициализира прясно всеки път, когато има извикване към този уеб елемент с помощта на driver.findElement () или драйвер .findElements ().
Ето защо, с нова стъпка на driver.findElement () за елемент, структурата на DOM отново се сканира и на тази страница се извършва обновена идентификация на елемента.
System.setProperty('webdriver.chrome.driver', 'C:\eclipse-workspace\automationframework\src\test\java\Drivers\chromedriver.exe'); WebDriver driver = new ChromeDriver(); driver.get('http://www.nseindia.com/'); WebElement searchNSETxt=driver.findElement(By.id(“searchBox”)); searchNSETxt.sendkeys(“investment”);
Използване на POM с Pagefactory:
Освен използването на анотация @FindBy вместо метода driver.findElement (), долният кодов фрагмент се използва допълнително за Pagefactory. Статичният метод initElements () от клас PageFactory се използва за инициализиране на всички елементи на потребителския интерфейс на страницата веднага щом страницата се зареди.
public PagefactoryClass(WebDriver driver) { this.driver = driver; PageFactory.initElements(driver, this); }
Горната стратегия прави подхода PageFactory малко по-различен от обичайния POM. В обичайния POM уеб елементът трябва да бъде изрично инициализиран, докато в подхода Pagefactory всички елементи се инициализират с initElements (), без изрично инициализиране на всеки уеб елемент.
Например: Ако WebElement е деклариран, но не е инициализиран в обичайния POM, тогава се извежда грешка „инициализиране на променлива“ или NullPointerException. Следователно в обичайния POM всеки WebElement трябва да бъде изрично инициализиран. PageFactory идва с предимство пред обичайния POM в този случай.
Нека не инициализираме уеб елемента BDate (POM без Pagefactory), можете да видите, че грешката ‘Initialize variable’ се показва и подканва потребителя да я инициализира до null, следователно не можете да приемете, че елементите се инициализират имплицитно при тяхното локализиране.
Изрично инициализиран елемент BDate (POM без Pagefactory):
Сега, нека разгледаме няколко случая на пълна програма, използваща PageFactory, за да изключим всякакви неясноти в разбирането на аспекта на изпълнението.
Пример 1:
- Отидете на „http://www.nseindia.com/“
- От падащото меню до полето за търсене изберете „Валутни деривати“.
- Потърсете „USDINR“. Проверете текста „Американски долар-индийска рупия - USDINR“ на получената страница.
Структура на програмата:
- Създава се PagefactoryClass.java, която включва хранилище на обекти, използвайки концепция за фабрични страници за nseindia.com, което е конструктор за инициализиране на всички уеб елементи, метод selectCurrentDerivative () за избор на стойност от падащото поле на полето за търсене, selectSymbol (), за да изберете символ на страница, която се показва следваща и verifytext (), за да проверите дали заглавката на страницата е според очакванията или не.
- NSE_MainClass.java е основният файл на класа, който извиква всички горепосочени методи и изпълнява съответните действия на сайта на NSE.
PagefactoryClass.java
package com.pagefactory.knowledge; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.support.FindBy; import org.openqa.selenium.support.PageFactory; import org.openqa.selenium.support.ui.Select; public class PagefactoryClass { WebDriver driver; @FindBy(id = 'QuoteSearch') WebElement Searchbox; @FindBy(id = 'cidkeyword') WebElement Symbol; @FindBy(id = 'companyName') WebElement pageText; public PagefactoryClass(WebDriver driver) { this.driver = driver; PageFactory.initElements(driver, this); } public void selectCurrentDerivative(String derivative) { Select select = new Select(Searchbox); select.selectByVisibleText(derivative); // 'Currency Derivatives' } public void selectSymbol(String symbol) { Symbol.sendKeys(symbol); } public void verifytext() { if (pageText.getText().equalsIgnoreCase('U S Dollar-Indian Rupee - USDINR')) { System.out.println('Page Header is as expected'); } else System.out.println('Page Header is NOT as expected'); } }
NSE_MainClass.java
package com.pagefactory.knowledge; import java.util.List; import java.util.concurrent.TimeUnit; import org.openqa.selenium.By; import org.openqa.selenium.StaleElementReferenceException; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.chrome.ChromeDriver; public class NSE_MainClass { static PagefactoryClass page; static WebDriver driver; public static void main(String() args) { System.setProperty('webdriver.chrome.driver', 'C:\Users\eclipse-workspace\automation-framework\src\test\java\Drivers\chromedriver.exe'); driver = new ChromeDriver(); driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS); driver.get('https://www.nseindia.com/'); driver.manage().window().maximize(); test_Home_Page_ofNSE(); } public static void test_Home_Page_ofNSE() throws StaleElementReferenceException { page = new PagefactoryClass(driver); page.selectCurrentDerivative('Currency Derivatives'); page.selectSymbol('USD'); List Options = driver.findElements(By.xpath('//span(contains(.,'USD'))')); int count = Options.size(); for (int i = 0; i Пример 2:
- Отидете на „https://www.shoppersstop.com/brands“
- Отворете връзката Haute curry.
- Проверете дали страницата Haute Curry съдържа текста „Start New Something“.
Структура на програмата
- shopperstopPagefactory.java, който включва хранилище на обекти, използвайки концепция за pagefactory за shoppersstop.com, който е конструктор за инициализиране на всички уеб елементи, създава се методите closeExtraPopup () за обработка на изскачащо поле за предупреждение, clickOnHauteCurryLink (), за да кликнете върху Haute Curry Свържете и проверетеStartNewSomething (), за да проверите дали страницата Haute Curry съдържа текста „Започнете ново нещо“.
- Shopperstop_CallPagefactory.java е основният файл на класа, който извиква всички горепосочени методи и изпълнява съответните действия на сайта на NSE.
shopperstopPagefactory.java
package com.inportia.automation_framework; import org.openqa.selenium.JavascriptExecutor; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.support.FindBy; import org.openqa.selenium.support.PageFactory; public class shopperstopPagefactory { WebDriver driver; @FindBy(id='firstVisit') WebElement extrapopup; @FindBy(xpath='//img(@src='https://sslimages.shoppersstop.com /sys-master/root/haf/h3a/9519787376670/brandMedia_HauteCurry_logo.png')') WebElement HCLink; @FindBy(xpath='/html/body/main/footer/div(1)/p') WebElement Startnew; public shopperstopPagefactory(WebDriver driver) { this.driver=driver; PageFactory.initElements(driver, this); } public void closeExtraPopup() { extrapopup.click(); } public void clickOnHauteCurryLink() { JavascriptExecutor js = (JavascriptExecutor) driver; js.executeScript('arguments(0).click();',HCLink); js.executeAsyncScript('window.setTimeout(arguments(arguments.length - 1), 10000);'); if(driver.getCurrentUrl().equals('https://www.shoppersstop.com/haute-curry')) { System.out.println('We are on the Haute Curry page'); } else { System.out.println('We are NOT on the Haute Curry page'); } } public void verifyStartNewSomething() { if (Startnew.getText().equalsIgnoreCase('Start Something New')) { System.out.println('Start new something text exists'); } else System.out.println('Start new something text DOESNOT exists'); } }
Shopperstop_CallPagefactory.java
package com.inportia.automation_framework; import java.util.concurrent.TimeUnit; import org.openqa.selenium.WebDriver; import org.openqa.selenium.chrome.ChromeDriver; public class Shopperstop_CallPagefactory extends shopperstopPagefactory { public Shopperstop_CallPagefactory(WebDriver driver) { super(driver); // TODO Auto-generated constructor stub } static WebDriver driver; public static void main(String() args) { System.setProperty('webdriver.chrome.driver', 'C:\eclipse-workspace\automation-framework\src\test\java\Drivers\chromedriver.exe'); driver = new ChromeDriver(); Shopperstop_CallPagefactory s1=new Shopperstop_CallPagefactory(driver); driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS); driver.get('https://www.shoppersstop.com/brands'); s1.clickOnHauteCurryLink(); s1.verifyStartNewSomething(); } }
POM Използване на Page Factory
Видео уроци - POM с Page Factory
Част I
Част II
Клас Factory се използва, за да направи използването на Page Objects по-просто и лесно.
- Първо, трябва да намерим уеб елементите чрез анотация @FindBy в класове на страници .
- След това инициализирайте елементите, като използвате initElements (), когато създавате инстанция на класа на страницата.
# 1) @FindBy:
Анотацията @FindBy се използва в PageFactory за намиране и деклариране на уеб елементите с помощта на различни локатори.Тук предаваме атрибута, както и стойността му, използвана за намиране на уеб елемента, в анотацията @FindBy и след това се декларира WebElement.
Има 2 начина, по които анотацията може да се използва.
Например:
@FindBy(how = How.ID, using='EmailAddress') WebElement Email; @FindBy(id='EmailAddress') WebElement Email;
Първият обаче е стандартният начин за деклариране на WebElements.
‘Как’ е клас и има статични променливи като ID, XPATH, CLASSNAME, LINKTEXT и т.н.
'използвайки' - За да присвоите стойност на статична променлива.
В горното пример , използвахме атрибута ‘id’, за да намерим уеб елемента ‘Email’. По същия начин можем да използваме следните локатори с анотациите @FindBy:
- className
- css
- име
- xpath
- tagName
- linkText
- частиченLinkText
# 2) initElements ():
InitElements е статичен метод на клас PageFactory, който се използва за инициализиране на всички уеб елементи, разположени от анотацията @FindBy. По този начин, инстанциране на класовете Page лесно.
initElements(WebDriver driver, java.lang.Class pageObjectClass)
Трябва също да разберем, че POM следва принципите на OOPS.
- WebElements се декларират като променливи на частни членове (Скриване на данни).
- Обвързване на WebElements със съответните методи (капсулиране).
Стъпки за създаване на POM с помощта на Page Factory Pattern
# 1) Създайте отделен файл на Java клас за всяка уеб страница.
# две) Във всеки клас всички WebElements трябва да бъдат декларирани като променливи (с помощта на анотация - @FindBy) и инициализирани с помощта на метода initElement (). Декларираните WebElements трябва да бъдат инициализирани, за да се използват в методите за действие.
# 3) Определете съответните методи, действащи върху тези променливи.
Нека вземем пример за прост сценарий:
- Отворете URL адреса на приложение.
- Въведете имейл адрес и данни за парола.
- Щракнете върху бутона Вход.
- Проверете успешното съобщение за вход на страницата за търсене.
Страничен слой
Тук имаме 2 страници,
- Начална страница - Страницата, която се отваря при въвеждане на URL адреса и където въвеждаме данните за влизане.
- SearchPage - Страница, която се показва след успешно влизане.
В Page Layer всяка страница в уеб приложението се декларира като отделен Java клас и там се споменават неговите локатори и действия.
Стъпки за създаване на POM с пример в реално време
# 1) Създайте Java клас за всяка страница:
В това пример , ще имаме достъп до 2 уеб страници, страници „Начало“ и „Търсене“.
Следователно, ние ще създадем 2 Java класа в Page Layer (или в даден пакет, com.automation.pages).
Package Name :com.automation.pages HomePage.java SearchPage.java
# 2) Определете WebElements като променливи, използвайки Annotation @FindBy:
Бихме взаимодействали с:
- Имейл, парола, поле за бутон за вход на началната страница.
- Успешно съобщение на страницата за търсене.
Така че ще дефинираме WebElements с помощта на @FindBy
Например: Ако ще идентифицираме EmailAddress с помощта на атрибут id, тогава неговата декларация на променлива е
//Locator for EmailId field @FindBy(how=How.ID,using='EmailId') private WebElementEmailIdAddress;
# 3) Създайте методи за действия, извършвани в WebElements.
По-долу се извършват действия на WebElements:
- Въведете действие в полето Email Address.
- Въведете действие в полето Парола.
- Щракнете върху действие върху бутона за вход.
Например, Потребителски дефинирани методи се създават за всяко действие в WebElement като,
public void typeEmailId(String Id){ driver.findElement(EmailAddress).sendKeys(Id) }
Тук Id се предава като параметър в метода, тъй като входът ще бъде изпратен от потребителя от основния тестов случай.
Забележка :Конструктор трябва да бъде създаден във всеки от класа в слоя на страницата, за да се получи екземпляр на драйвера от основния клас в тестовия слой и също да се инициализират WebElements (обекти на страници), декларирани в класа на страницата с помощта на PageFactory.InitElement () .
Тук не инициираме драйвера, а по-скоро неговият екземпляр се получава от основния клас, когато се създава обектът от класа на слоя страница.
InitElement () - се използва за инициализиране на декларираните WebElements, като се използва екземпляр на драйвер от основния клас. С други думи, WebElements се създават с помощта на екземпляра на драйвера. Само след като WebElements са инициализирани, те могат да се използват в методите за извършване на действия.
За всяка страница се създават два Java класа, както е показано по-долу:
HomePage.java
//package com.automation.pages; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; public class HomePage { WebDriver driver; // Locator for Email Address @FindBy(how=How.ID,using='EmailId') private WebElement EmailIdAddress; // Locator for Password field @FindBy(how=How.ID,using='Password ') private WebElement Password; // Locator for SignIn Button @FindBy(how=How.ID,using='SignInButton') private WebElement SignInButton; // Method to type EmailId public void typeEmailId(String Id){ driver.findElement(EmailAddress).sendKeys(Id) } // Method to type Password public void typePassword(String PasswordValue){ driver.findElement(Password).sendKeys(PasswordValue) } // Method to click SignIn Button public void clickSignIn(){ driver.findElement(SignInButton).click() } // Constructor // Gets called when object of this page is created in MainClass.java public HomePage(WebDriver driver) { // 'this' keyword is used here to distinguish global and local variable 'driver' //gets driver as parameter from MainClass.java and assigns to the driver instance in this class this.driver=driver; PageFactory.initElements(driver,this); // Initialises WebElements declared in this class using driver instance. } }
SearchPage.Java
//package com.automation.pages; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; public class SearchPage{ WebDriver driver; // Locator for Success Message @FindBy(how=How.ID,using='Message') private WebElement SuccessMessage; // Method that return True or False depending on whether the message is displayed public Boolean MessageDisplayed(){ Boolean status = driver.findElement(SuccessMessage).isDisplayed(); return status; } // Constructor // This constructor is invoked when object of this page is created in MainClass.java public SearchPage(WebDriver driver) { // 'this' keyword is used here to distinguish global and local variable 'driver' //gets driver as parameter from MainClass.java and assigns to the driver instance in this class this.driver=driver; PageFactory.initElements(driver,this); // Initialises WebElements declared in this class using driver instance. } }
Тестов слой
В този клас са приложени тестови случаи. Създаваме отделен пакет, например, com.automation.test и след това създаваме Java клас тук (MainClass.java)
Стъпки за създаване на тестови случаи:
- Инициализирайте драйвера и отворете приложението.
- Създайте обект от PageLayer Class (за всяка уеб страница) и предайте екземпляра на драйвера като параметър.
- Използвайки създадения обект, извикайте методите в PageLayer Class (за всяка уеб страница), за да извършите действия / проверка.
- Повторете стъпка 3, докато се извършат всички действия и след това затворете драйвера.
//package com.automation.test; import org.openqa.selenium.WebDriver; import org.openqa.selenium.chrome.ChromeDriver; public class MainClass { public static void main(String() args) { System.setProperty('webdriver.chrome.driver','./exefiles/chromedriver.exe'); WebDriver driver= new ChromeDriver(); driver.manage().window().maximize(); driver.get('URL mentioned here'); // Creating object of HomePage and driver instance is passed as parameter to constructor of Homepage.Java HomePage homePage= new HomePage(driver); // Type EmailAddress homePage.typeEmailId('abc@ymail.com'); // EmailId value is passed as paramter which in turn will be assigned to the method in HomePage.Java // Type Password Value homePage.typePassword('password123'); // Password value is passed as paramter which in turn will be assigned to the method in HomePage.Java // Click on SignIn Button homePage.clickSignIn(); // Creating an object of LoginPage and driver instance is passed as parameter to constructor of SearchPage.Java SearchPage searchPage= new SearchPage(driver); //Verify that Success Message is displayed Assert.assertTrue(searchPage.MessageDisplayed()); //Quit browser driver.quit(); } }
Йерархия на типа анотация, използвана за деклариране на WebElements
Анотациите се използват за изграждане на стратегия за местоположение за елементите на потребителския интерфейс.
# 1) @FindBy
Що се отнася до Pagefactory, @FindBy действа като магическа пръчка. Той добавя цялата сила към концепцията. Вече сте наясно, че пояснението @FindBy в Pagefactory изпълнява същото като това на driver.findElement () в обичайния обектен модел на страница. Използва се за намиране на WebElement / WebElements с един критерий .
# 2) @FindBys
Използва се за намиране на WebElement с повече от един критерий и трябва да отговарят на всички дадени критерии. Тези критерии трябва да бъдат споменати в отношенията родител-дете. С други думи, това използва условна връзка AND за намиране на WebElements, използвайки посочените критерии. Той използва множество @FindBy, за да дефинира всеки критерий.
Например:
HTML изходен код на WebElement:
В POM:
@FindBys({ @FindBy(id = 'searchId_1'), @FindBy(name = 'search_field') }) WebElementSearchButton;
В горния пример WebElement ‘SearchButton’ се намира само ако е такъв съвпада и с двете критериите, чиято стойност на id е „searchId_1“, а стойността на името е „search_field“. Моля, обърнете внимание, че първите критерии принадлежат на родителски маркер, а вторите критерии за дъщерен маркер.
# 3) @FindAll
Използва се за намиране на WebElement с повече от един критерий и трябва да отговаря на поне един от дадените критерии. Това използва ИЛИ условни връзки, за да намери WebElements. Той използва множество @FindBy, за да дефинира всички критерии.
Например:
HTML код на източника:
В POM:
@FindBys({ @FindBy(id = 'UsernameNameField_1'), // doesn’t match @FindBy(name = 'User_Id') //matches @FindBy(className = “UserName_r”) //matches }) WebElementUserName;
В горния пример WebElement ‘Потребителско име се намира, ако е съответства на поне един от посочените критерии.
# 4) @CacheLookUp
Когато WebElement се използва по-често в тестови случаи, Selenium търси WebElement всеки път, когато се изпълнява тестовият скрипт. В тези случаи, при които определени WebElements се използват глобално за всички TC ( Например, Сценарият за влизане се случва за всеки TC), тази анотация може да се използва за поддържане на тези WebElements в кеш паметта, след като бъде прочетена за първи път.
Това от своя страна помага на кода да се изпълнява по-бързо, защото всеки път, когато не се налага да търси WebElement на страницата, по-скоро може да получи референцията си от паметта.
Това може да бъде като префикс с който и да е от @FindBy, @FindBys и @FindAll.
Например:
@CacheLookUp @FindBys({ @FindBy(id = 'UsernameNameField_1'), @FindBy(name = 'User_Id') @FindBy(className = “UserName_r”) }) WebElementUserName;
Също така имайте предвид, че тази анотация трябва да се използва само за WebElements, чиято стойност на атрибута (като xpath, име на име, име на клас и т.н.) не се променя често. След като WebElement се намери за първи път, той поддържа референцията си в кеш паметта.
И така, след няколко дни се случва промяна в атрибута на WebElement, Selenium няма да може да намери елемента, тъй като той вече има стария си референтен файл в кеш паметта си и няма да вземе предвид скорошната промяна в WebElement.
Още на PageFactory.initElements ()
Сега, когато разбираме стратегията на Pagefactory за инициализиране на уеб елементите с помощта на InitElements (), нека се опитаме да разберем различните версии на метода.
Методът, както познаваме, взема обекта на драйвера и обекта на текущия клас като входни параметри и връща обекта на страницата чрез неявна и активна инициализация на всички елементи на страницата.
На практика използването на конструктора, както е показано в горния раздел, е по-предпочитано пред другите начини за неговото използване.
Алтернативните начини за извикване на метода са:
# 1) Вместо да използвате указателя “this”, можете да създадете текущия обект на клас, да му предадете екземпляра на драйвера и да извикате статичния метод initElements с параметри, т.е. обектът на драйвер и обектът на класа, който току-що е създаден.
public PagefactoryClass(WebDriver driver) { //version 2 PagefactoryClass page=new PagefactoryClass(driver); PageFactory.initElements(driver, page); }
# две) Третият начин за инициализиране на елементи с помощта на клас Pagefactory е чрез използване на API, наречен „отражение“. Да, вместо да създаваме обект на клас с ключова дума „new“, classname.class може да бъде предаден като част от входния параметър initElements ().
public PagefactoryClass(WebDriver driver) { //version 3 PagefactoryClass page=PageFactory.initElements(driver, PagefactoryClass.class); }
често задавани въпроси
В # 1) Кои са различните стратегии за локатор, които се използват за @FindBy?
Отговор: Простият отговор на това е, че няма различни стратегии за локатор, които се използват за @FindBy.
Те използват същите 8 стратегии за локатор, които методът findElement () в обичайния POM използва:
- документ за самоличност
- име
- className
- xpath
- css
- tagName
- linkText
- частиченLinkText
В # 2) Има ли различни версии за използване и на анотациите @FindBy?
Отговор: Когато има уеб елемент за търсене, ние използваме пояснението @FindBy. Ще разгледаме алтернативните начини за използване на @FindBy заедно с различните стратегии за локатор.
Вече видяхме как да използваме версия 1 на @FindBy:
@FindBy(id = 'cidkeyword') WebElement Symbol;
Версия 2 на @FindBy е чрез предаване на входния параметър като Как и Използвайки .
Как търси стратегията за локатор, чрез която да бъде идентифициран вебелементът. Ключовата дума използвайки дефинира стойността на локатора.
Вижте по-долу за по-добро разбиране,
- How.ID търси елемента с помощта документ за самоличност стратегия и елементът, който се опитва да идентифицира, има id = cidkeyword.
@FindBy(how = How.ID, using = ' cidkeyword') WebElement Symbol;
- How.CLASS_NAME търси елемента с помощта className стратегия и елементът, който се опитва да идентифицира, има class = нов клас.
@FindBy(how = How.CLASS_NAME, using = 'newclass') WebElement Symbol;
В # 3) Има ли разлика между двете версии на @FindBy?
Отговор: Отговорът е Не, няма разлика между двете версии. Просто първата версия е по-къса и по-лесна в сравнение с втората версия.
В # 4) Какво да използвам в страницата на фабриката, в случай че има списък с уеб елементи, които трябва да бъдат разположени?
Отговор: В обичайния шаблон за дизайн на обект на страница имаме driver.findElements (), за да намерим множество елементи, принадлежащи към един и същ клас или име на етикет, но как да намерим такива елементи в случая на обектния модел на страница с Pagefactory? Най-лесният начин за постигане на такива елементи е да се използва същата анотация @FindBy.
Разбирам, че тази линия изглежда е драскаща за много от вас. Но да, това е отговорът на въпроса.
Нека разгледаме примера по-долу:
Използвайки обичайния обектен модел на страница без Pagefactory, вие използвате driver.findElements за намиране на множество елементи, както е показано по-долу:
private List multipleelements_driver_findelements = driver.findElements (By.class(“last”));
Същото може да се постигне с помощта на обектния модел на страница с Pagefactory, както е дадено по-долу:
@FindBy (how = How.CLASS_NAME, using = 'last') private List multipleelements_FindBy;
По принцип присвояването на елементите към списък от тип WebElement прави трика, независимо дали Pagefactory е бил използван или не, докато се идентифицират и намират елементите.
Въпрос # 5) Може ли дизайнът на обект на страница без pagefactory и с Pagefactory да се използва в една и съща програма?
Отговор: Да, както дизайнът на обект на страница без Pagefactory, така и с Pagefactory може да се използва в една и съща програма. Можете да преминете през програмата, дадена по-долу в Отговор на въпрос №6 за да видите как и двете се използват в програмата.
Едно нещо, което трябва да запомните, е, че концепцията Pagefactory с кешираната функция трябва да се избягва при динамични елементи, докато дизайнът на страничен обект работи добре за динамични елементи. Pagefactory обаче отговаря само на статични елементи.
В # 6) Има ли алтернативни начини за идентифициране на елементи въз основа на множество критерии?
най-добрият софтуер за заснемане на екрана windows 10
Отговор: Алтернативата за идентифициране на елементи въз основа на множество критерии е използването на анотациите @FindAll и @FindBys. Тези пояснения помагат да се идентифицират единични или множество елементи в зависимост от стойностите, получени от критериите, предадени в него.
# 1) @FindAll:
@FindAll може да съдържа множество @FindBy и ще върне всички елементи, които съответстват на който и да е @FindBy в един списък. @FindAll се използва за маркиране на поле на обект на страница, за да покаже, че справка трябва да използва серия от маркери @FindBy. След това ще търси всички елементи, които отговарят на който и да е от критериите FindBy.
Имайте предвид, че не се гарантира, че елементите са в реда на документите.
Синтаксисът за използване на @FindAll е както по-долу:
@FindAll( { @FindBy(how = How.ID, using = 'foo'), @FindBy(className = 'bar') } )
Обяснение: @FindAll ще търси и идентифицира отделни елементи, отговарящи на всеки от критериите @FindBy, и ще ги изброи. В горния пример първо ще търси елемент, чийто id = ”foo” и след това ще идентифицира втория елемент с className = ”bar”.
Ако приемем, че за всеки критерий FindBy е идентифициран по един елемент, @FindAll ще доведе до изброяване на съответно 2 елемента. Не забравяйте, че за всеки критерий могат да бъдат идентифицирани множество елементи. По този начин, с прости думи, @ FindAll действа еквивалентно на ИЛИ оператор по приетите критерии @FindBy.
# 2) @FindBys:
FindBys се използва за маркиране на поле на обект на страница, за да покаже, че търсенето трябва да използва поредица от маркери @FindBy във верига, както е описано в ByChained. Когато необходимите обекти на WebElement трябва да отговарят на всички дадени критерии, използвайте анотация @FindBys.
Синтаксисът за използване на @FindBys е както по-долу:
@FindBys( { @FindBy(name=”foo”) @FindBy(className = 'bar') } )
Обяснение: @FindBys ще търси и идентифицира елементи, отговарящи на всички критерии @FindBy, и ще ги изброи. В горния пример той ще търси елементи, чието име = ”foo” и className = ”bar”.
@FindAll ще доведе до изброяване на 1 елемент, ако приемем, че има един елемент, идентифициран с името и className в дадените критерии.
Ако няма нито един елемент, който да отговаря на всички приети условия на FindBy, тогава резултантната стойност на @FindBys ще бъде нула елементи. Може да има списък с идентифицирани уеб елементи, ако всички условия отговарят на множество елементи. С прости думи, @ FindBys действа еквивалентно на И оператор по приетите критерии @FindBy.
Нека да видим изпълнението на всички горепосочени анотации чрез подробна програма:
Ще модифицираме програмата www.nseindia.com, дадена в предишния раздел, за да разберем изпълнението на анотациите @FindBy, @FindBys и @FindAll
# 1) Хранилището на обекти на PagefactoryClass се актуализира по-долу:
Списък newlist = driver.findElements (By.tagName (“a”));
@FindBy (как = Как. TAG_NAME , като се използва = “a”)
частни Списък findbyvalue;
@FindAll ({ @FindBy (className = “sel”), @FindBy (xpath = ”// a (@ id =’ tab5 ′) ”)}))
частни Списък findallvalue;
@FindBys ({ @FindBy (className = “sel”), @FindBy (xpath = ”// a (@ id =’ tab5 ′) ”)}))
частни Списък findbysvalue;
# 2) Нов метод seeHowFindWorks () се записва в PagefactoryClass и се извиква като последния метод в основния клас.
Методът е както по-долу:
private void seeHowFindWorks() { System.out.println('driver.findElements(By.tagName()) '+newlist.size()); System.out.println('count of @FindBy- list elements '+findbyvalue.size()); System.out.println('count of @FindAll elements '+findallvalue.size()); for(int i=0;i По-долу е даден резултатът, показан в прозореца на конзолата след изпълнението на програмата:

Нека сега се опитаме да разберем кода в детайли:
# 1) Чрез шаблона за дизайн на обекта на страницата елементът „нов списък“ идентифицира всички маркери с котва „а“. С други думи, получаваме брой на всички връзки на страницата.
Научихме, че pagefactory @FindBy върши същата работа като тази на driver.findElement (). Елементът findbyvalue е създаден, за да получи броя на всички връзки на страницата чрез стратегия за търсене, имаща концепция за страница.
Доказва се правилно, че и driver.findElement (), и @FindBy вършат една и съща работа и идентифицират едни и същи елементи. Ако погледнете екранната снимка на резултантния прозорец на конзолата по-горе, броят на връзките, идентифицирани с елемента newlist и този на findbyvalue са равни, т.е. 299 връзки, намерени на страницата.
Резултатът се показа по-долу:
driver.findElements(By.tagName()) 299 count of @FindBy- list elements 299
# две) Тук ние разработваме работата на анотацията @FindAll, която ще се отнася до списъка на уеб елементите с името findallvalue.
Внимателно разглеждайки всеки критерий @FindBy в анотацията @FindAll, първият критерий @FindBy търси елементи с className = 'sel', а вторият критерий @FindBy търси конкретен елемент с XPath = “// a (@ id = 'tab5')
Нека сега натиснем F12, за да проверим елементите на страницата nseindia.com и да получим определени ясноти за елементи, отговарящи на критериите @FindBy.
На страницата има два елемента, съответстващи на className = ”sel”:
да се) Елементът „Основи“ има списъчен маркер, т.е.
с className = ”sel”. Вижте снимка по-долу

б) Друг елемент „Книга за поръчки“ има XPath с котва, който има името на класа като „sel“.

° С) Вторият @FindBy с XPath има котва, която документ за самоличност е „ tab5 ”. Има само един елемент, идентифициран в отговор на търсенето, който е Основи.
Вижте снимката по-долу:

Когато тестът nseindia.com беше изпълнен, получихме броя на елементите, търсени от.
@FindAll as 3. Елементите за findallvalue при показване бяха: Основи като 0тииндекс елемент, книга за поръчки като 1улиндекс елемент и Основи отново като 2ndиндексен елемент. Вече научихме, че @FindAll идентифицира елементи за всеки критерий @FindBy поотделно.
Съгласно същия протокол за първото критерийно търсене, т.е. className = „sel”, той идентифицира два елемента, отговарящи на условието, и извлича „Основи“ и „Книга за поръчки“.
След това се премести към следващия критерий @FindBy и според xpath, даден за втория @FindBy, той може да извлече елемента „Основи“. Ето защо той най-накрая идентифицира съответно 3 елемента.
По този начин той не получава елементите, отговарящи на нито едно от условията @FindBy, но се справя отделно с всеки от @FindBy и идентифицира елементите по същия начин. Освен това в текущия пример също видяхме, че той не следи дали елементите са уникални ( E.g. Елементът „Основи“ в този случай, който се показва два пъти като част от резултата от двата критерия @FindBy)
# 3) Тук ние разработваме работата на анотацията @FindBys, която ще се отнася до списъка на уеб елементите с името findbysvalue. И тук първият критерий @FindBy търси елементи с className = ’sel’, а вторият критерий @FindBy търси конкретен елемент с xpath = “// a (@ id =” tab5 ”).
Сега, когато знаем, елементите, идентифицирани за първото условие @FindBy, са „Основи“ и „Книга за поръчки“, а този за втория критерий @FindBy е „Основи“.
И така, как резултатът от @FindBys ще бъде различен от @FindAll? В предишния раздел научихме, че @FindBys е еквивалентен на условния оператор И и следователно търси елемент или списък с елементи, които отговарят на всички условия @FindBy.
Според настоящия ни пример стойността „Основи“ е единственият елемент, който има class = ”sel” и id = ”tab5”, като по този начин отговаря на двете условия. Ето защо размерът на @FindBys в тестовата кутия е 1 и показва стойността като „Основи“.
Кеширане на елементите в Pagefactory
Всеки път, когато се зарежда страница, всички елементи на страницата се търсят отново чрез извикване на обаждане чрез @FindBy или driver.findElement () и има ново търсене на елементите на страницата.
По-голямата част от времето, когато елементите са динамични или продължават да се променят по време на изпълнение, особено ако са елементи AJAX, със сигурност има смисъл, че при всяко зареждане на страницата има ново търсене на всички елементи на страницата.
Когато уеб страницата има статични елементи, кеширането на елемента може да помогне по множество начини. Когато елементите са кеширани, не е нужно да намира елементите отново при зареждане на страницата, вместо това може да препраща към хранилището на кеширани елементи. Това спестява много време и повишава производителността.
Pagefactory предоставя тази функция за кеширане на елементите с помощта на анотация @CacheLookUp .
Анотацията казва на драйвера да използва същия екземпляр на локатора от DOM за елементите и да не ги търси отново, докато методът initElements на pagefactory видно допринася за съхраняване на кеширания статичен елемент. InitElements вършат кеширането на елементите.
Това прави концепцията за pagefactory специална спрямо обикновения шаблон за дизайн на обект на страница. Той идва със собствени плюсове и минуси, които ще обсъдим малко по-късно. Например бутонът за вход на началната страница на Facebook е статичен елемент, който може да се кешира и е идеален елемент за кеширане.
Нека сега разгледаме как да приложим анотацията @CacheLookUp
Първо ще трябва да импортирате пакет за Cachelookup, както е показано по-долу:
import org.openqa.selenium.support.CacheLookup
По-долу е фрагментът, показващ дефиницията на елемент с помощта на @CacheLookUp. Веднага след като UniqueElement бъде търсен за първи път, initElement () съхранява кешираната версия на елемента, така че следващият път, когато драйверът не търси елемента вместо това, той се позовава на същия кеш и изпълнява действието върху елемента вдясно далеч.
@FindBy(id = 'unique') @CacheLookup private WebElement UniqueElement;
Нека сега да видим чрез действителна програма как действията върху кеширания уеб елемент са по-бързи от тези върху некеширания уеб елемент:
Подобрявайки програмата nseindia.com допълнително, написах още един нов метод monitorPerformance (), в който създавам кеширан елемент за полето за търсене и некеширан елемент за същото поле за търсене.
След това се опитвам да взема името на маркера на елемента 3000 пъти както за кеширания, така и за некеширания елемент и се опитвам да преценя времето, необходимо за изпълнение на задачата, както от кеширания, така и от кеширания елемент.
Обмислял съм 3000 пъти, за да можем да видим видима разлика във времето за двете. Ще очаквам, че кешираният елемент трябва да завърши получаването на името на маркера 3000 пъти за по-кратко време в сравнение с това на некеширания елемент.
Сега знаем защо кешираният елемент трябва да работи по-бързо, т.е. драйверът е инструктиран да не търси елемента след първото търсене, а директно да продължи да работи върху него, а това не е случаят с некеширания елемент, за който се извършва търсенето на елемента всички 3000 пъти и след това действието се извършва върху него.
По-долу е даден кодът за метода monitorPerformance ():
private void monitorPerformance() { //non cached element long NoCache_StartTime = System.currentTimeMillis(); for(int i = 0; i <3000; i ++) { Searchbox.getTagName(); } long NoCache_EndTime = System.currentTimeMillis(); long NoCache_TotalTime=(NoCache_EndTime-NoCache_StartTime)/1000; System.out.println('Response time without caching Searchbox ' + NoCache_TotalTime+ ' seconds'); //cached element long Cached_StartTime = System.currentTimeMillis(); for(int i = 0; i < 3000; i ++) { cachedSearchbox.getTagName(); } long Cached_EndTime = System.currentTimeMillis(); long Cached_TotalTime=(Cached_EndTime - Cached_StartTime)/1000; System.out.println('Response time by caching Searchbox ' + Cached_TotalTime+ ' seconds'); }
При изпълнението ще видим резултата по-долу в прозореца на конзолата:
Според резултата задачата върху некеширания елемент е завършена през 82 секунди, докато времето, необходимо за изпълнение на задачата на кеширания елемент, беше само 37 секунди. Това наистина е видима разлика във времето за реакция както на кеширания, така и на некеширания елемент.

В # 7) Какви са плюсовете и минусите на анотацията @CacheLookUp в концепцията на Pagefactory?
Отговор:
Плюсове @CacheLookUp и възможни ситуации за използването му:
@CacheLookUp е осъществимо, когато елементите са статични или изобщо не се променят, докато страницата се зарежда. Такива елементи не променят времето за изпълнение. В такива случаи е препоръчително да използвате анотацията, за да подобрите общата скорост на изпълнението на теста.
Недостатъци на анотацията @CacheLookUp:
Най-големият недостатък на кеширането на елементи с анотацията е страхът от често получаване на StaleElementReferenceExceptions.
Динамичните елементи се опресняват доста често с тези, които са податливи на бърза промяна в рамките на няколко секунди или минути от интервала от време.
По-долу има няколко такива случая на динамичните елементи:
- Наличие на хронометър на уеб страницата, който поддържа актуализиране на таймера всяка секунда.
- Рамка, която постоянно актуализира отчета за времето.
- Страница, отчитаща актуализациите на Sensex на живо.
Те изобщо не са идеални или изпълними за използването на анотацията @CacheLookUp. Ако го направите, рискувате да получите изключението на StaleElementReferenceExceptions.
При кеширането на такива елементи, по време на тестовото изпълнение, DOM на елементите се променя, но драйверът търси версията на DOM, която вече е била съхранена по време на кеширането. Това прави остарелия елемент да бъде търсен от драйвера, който вече не съществува на уеб страницата. Ето защо се хвърля StaleElementReferenceException.
Фабрични класове:
Pagefactory е концепция, изградена върху множество фабрични класове и интерфейси. Ще научим за няколко фабрични класа и интерфейси тук в този раздел. Малко от които ще разгледаме са AjaxElementLocatorFactory , ElementLocatorFactory и DefaultElementFactory.
Замисляли ли сме се дали Pagefactory предоставя някакъв начин за включване на имплицитно или явно изчакване на елемента, докато се изпълни определено условие ( Пример: Докато елемент е видим, активиран, кликващ и т.н.)? Ако да, ето подходящ отговор на него.
AjaxElementLocatorFactory е един от значимите участници във всички фабрични класове. Предимството на AjaxElementLocatorFactory е, че можете да зададете стойност на времето за изчакване за уеб елемент на класа на обектната страница.
Въпреки че Pagefactory не предоставя изрична функция за изчакване, обаче има вариант за имплицитно изчакване с помощта на класа AjaxElementLocatorFactory . Този клас може да се използва вграден, когато приложението използва компоненти и елементи на Ajax.
Ето как го прилагате в кода. В рамките на конструктора, когато използваме метода initElements (), можем да използваме AjaxElementLocatorFactory, за да осигурим неявно изчакване на елементите.
PageFactory.initElements(driver, this); can be replaced with PageFactory.initElements( new AjaxElementLocatorFactory(driver, 20), this);
Горният втори ред на кода предполага, че драйверът трябва да зададе време за изчакване от 20 секунди за всички елементи на страницата, когато всеки от неговите зареждания и ако някой от елементите не бъде намерен след изчакване от 20 секунди, се изхвърля „NoSuchElementException“ за този липсващ елемент.
Можете също да дефинирате чакането, както е показано по-долу:
public pageFactoryClass(WebDriver driver) { ElementLocatorFactory locateMe = new AjaxElementLocatorFactory(driver, 30); PageFactory.initElements(locateMe, this); this.driver = driver; }
Горният код работи перфектно, защото класът AjaxElementLocatorFactory реализира интерфейса ElementLocatorFactory.
Тук родителският интерфейс (ElementLocatorFactory) се отнася до обекта на дъщерния клас (AjaxElementLocatorFactory). Следователно, концепцията на Java за „upcasting“ или „полиморфизъм по време на изпълнение“ се използва, докато се присвоява време за изчакване с помощта на AjaxElementLocatorFactory.
По отношение на това как работи технически, AjaxElementLocatorFactory първо създава AjaxElementLocator, използвайки SlowLoadableComponent, който може да не е завършил зареждането, когато load () се върне. След извикване на load () методът isLoaded () трябва да продължи да се проваля, докато компонентът се зареди напълно.
С други думи, всички елементи ще бъдат търсени прясно всеки път, когато елемент бъде достъпен в кода чрез извикване на извикване на locator.findElement () от класа AjaxElementLocator, който след това прилага време за изчакване до зареждане чрез клас SlowLoadableComponent.
Освен това, след задаване на изчакване чрез AjaxElementLocatorFactory, елементите с @CacheLookUp анотация вече няма да се кешират, тъй като анотацията ще бъде игнорирана.
Има и вариант на това как можеш обадете се на initElements () метод и как вие не трябва обадете се на AjaxElementLocatorFactory за да зададете изчакване за елемент.
# 1) Можете също така да посочите име на елемент вместо обекта на драйвера, както е показано по-долу в метода initElements ():
PageFactory.initElements( , this);
initElements () методът в горния вариант извиква вътрешно извикване на клас DefaultElementFactory и конструкторът на DefaultElementFactory приема интерфейсния обект SearchContext като входен параметър. Обектът на уеб драйвер и уеб елемент принадлежат към интерфейса SearchContext.
В този случай методът initElements () ще се инициализира предварително само към споменатия елемент и не всички елементи на уеб страницата ще бъдат инициализирани.
# две) Ето обаче един интересен обрат към този факт, който гласи как не трябва да извиквате обект AjaxElementLocatorFactory по специфичен начин. Ако използвам горния вариант на initElements () заедно с AjaxElementLocatorFactory, тогава той ще се провали.
Пример: Кодът по-долу, т.е. предаването на име на елемент вместо обект на драйвер на дефиницията AjaxElementLocatorFactory няма да работи, тъй като конструкторът за класа AjaxElementLocatorFactory приема само обект на уеб драйвер като входен параметър и следователно обектът SearchContext с уеб елемент няма да работи за него.
PageFactory.initElements(new AjaxElementLocatorFactory(, 10), this);
В # 8) Използването на pagefactory е осъществима опция спрямо обикновения шаблон за дизайн на обект на страница?
Отговор: Това е най-важният въпрос, който хората имат, и затова се сетих да го отговоря в края на урока. Вече знаем „влизането и излизането“ на Pagefactory, като се започне от неговите концепции, използвани анотации, допълнителни функции, които поддържа, внедряване чрез код, плюсовете и минусите.
И все пак ние оставаме при този основен въпрос, че ако pagefactory има толкова много добри неща, защо да не се придържаме към неговото използване.
Pagefactory идва с концепцията за CacheLookUp, която видяхме, че не е осъществима за динамични елементи като стойности на елемента, които се актуализират често. И така, pagefactory без CacheLookUp, добре ли е да отидете? Да, ако xpaths са статични.
Загубата обаче е, че приложението на модерната епоха е изпълнено с тежки динамични елементи, при които знаем, че дизайнът на обект на страница без pagefactory работи в крайна сметка добре, но дали концепцията на pagefactory работи еднакво добре с динамични xpaths? Може би не. Ето един бърз пример:
На уеб страницата nseindia.com виждаме таблица, дадена по-долу.

Xpath на таблицата е
'//*(@id='tab9Content')/table/tbody/tr(+count+)/td(1)'
Искаме да извлечем стойности от всеки ред за първата колона „Купете количество“. За да направим това, ще трябва да увеличим брояча на редовете, но индексът на колоната ще остане 1. Няма начин да можем да предадем този динамичен XPath в анотацията @FindBy, тъй като анотацията приема стойности, които са статични и не може да се предава променлива то.
Ето къде страничната фабрика се проваля напълно, докато обичайният POM работи чудесно с нея. Можете лесно да използвате цикъл for, за да увеличите индекса на редове, като използвате такива динамични xpaths в метода driver.findElement ().
Заключение
Page Object Model е дизайнерска концепция или модел, използван в рамката за автоматизация на Selenium.
Именуването на конвекция на методи е удобно за потребителя в Page Object Model. Кодът в POM е лесен за разбиране, многократна употреба и поддръжка. В POM, ако има някаква промяна в уеб елемента, тогава е достатъчно да направите промените в съответния му клас, вместо да редактирате всички класове.
Pagefactory точно като обичайния POM е прекрасна концепция за прилагане. Трябва обаче да знаем къде е възможен обичайният POM и къде Pagefactory подхожда добре. В статичните приложения (където и XPath, и елементите са статични), Pagefactory може да бъде внедрен с допълнителни предимства от по-добра производителност.
Като алтернатива, когато приложението включва както динамични, така и статични елементи, може да имате смесено изпълнение на pom с Pagefactory и това без Pagefactory според възможността за всеки уеб елемент.
Автор: Този урок е написан от Shobha D. Тя работи като ръководител на проекта и идва с 9+ години опит в ръчно, автоматизиране (Selenium, IBM Rational Functional Tester, Java) и API тестване (SOAPUI и Rest assured in Java) .
Сега към вас, за по-нататъшно внедряване на Pagefactory.
Честито проучване !!!
=> Посетете тук, за да научите селен от нулата.
Препоръчително четене
- 30+ най-добри урока за селен: Научете селен с реални примери
- Ефективни сценарии за скриптове и отстраняване на неизправности при селен - Урок №27 за селен
- Отстраняване на грешки в скриптове за селен с регистрационни файлове (Урок за Log4j) - Урок за селен # 26
- Въведение в JUnit Framework и нейното използване в Selenium Script - Селен Урок # 11
- 7 фактора, влияещи върху тестовата оценка на проекта за автоматизация на селен - Урок № 32 за селен
- Твърдения в селен с помощта на рамки Junit и TestNG
- Как да използвам TestNG Framework за създаване на селенови скриптове - TestNG Selenium Tutorial # 12
- Научете как да използвате TestNG анотации в селен (с примери)