page object model with page factory selenium tutorial
Aquest tutorial detallat explica tot sobre el model d'objectes de pàgina (POM) amb Pagefactory utilitzant exemples. També podeu conèixer la implementació de POM a Selenium:
En aquest tutorial, entendrem com crear un model d'objectes de pàgina mitjançant l'enfocament de fàbrica de pàgines. Ens centrarem en:
- Classe de fàbrica
- Com es crea un POM bàsic mitjançant el patró de fàbrica de pàgines
- Diferents anotacions utilitzades en l'enfocament de fàbrica de pàgines
Abans de veure què és Pagefactory i com es pot utilitzar juntament amb el model d'objectes de pàgina, entenem què és el model d'objectes de pàgina que normalment es coneix com POM.
=> Visiteu aquí per veure la sèrie de formació Selenium per a tothom.
Què aprendreu:
- Què és el model d'objectes de pàgina (POM)?
- Què és Pagefactory?
- POM mitjançant la fàbrica de pàgines
- Preguntes freqüents
- Conclusió
Què és el model d'objectes de pàgina (POM)?
Les terminologies teòriques descriuen el Model d'objectes de pàgina com a patró de disseny utilitzat per construir un dipòsit d'objectes per als elements web disponibles a l'aplicació que es prova. Pocs altres hi fan referència com a marc per a l'automatització de Selenium per a l'aplicació donada en prova.
Tot i això, el que he entès sobre el terme Model d'objectes de pàgina és:
# 1) És un patró de disseny on teniu un fitxer de classe Java independent que correspon a cada pantalla o pàgina de l'aplicació. El fitxer de classe pot incloure el repositori d'objectes dels elements de la IU, així com mètodes.
# 2) En cas que hi hagi nombrosos elements web en una pàgina, la classe de dipòsit d'objectes d'una pàgina es pot separar de la classe que inclou mètodes per a la pàgina corresponent.
Exemple: Si la pàgina Registra compte té molts camps d’entrada, hi pot haver una classe RegisterAccountObjects.java que formi el repositori d’objectes per als elements de la interfície d’usuari a la pàgina de comptes de registre.
Es podria crear un fitxer de classe RegisterAccount.java independent que estengui o hereti RegisterAccountObjects que inclogui tots els mètodes que realitzen diferents accions a la pàgina.
# 3) A més, hi pot haver un paquet genèric amb un fitxer {roperties, dades de proves d'Excel i mètodes comuns sota un paquet.
Exemple: DriverFactory que es podria utilitzar molt fàcilment a totes les pàgines de l'aplicació
Entendre POM amb exemple
Comprovar aquí per obtenir més informació sobre POM.
A continuació es mostra una instantània de la pàgina web:
En fer clic a cadascun d’aquests enllaços es redirigirà l’usuari a una pàgina nova.
Aquí teniu la instantània de com es crea l’estructura del projecte amb Selenium mitjançant el model d’objectes de pàgina corresponent a cada pàgina del lloc web. Cada classe Java inclou repositori d'objectes i mètodes per dur a terme diferents accions a la pàgina.
A més, hi haurà un altre fitxer de classe JUNIT o TestNG o Java que invoca trucades a fitxers de classe d’aquestes pàgines.
Per què fem servir el model d'objectes de pàgina?
Hi ha novetats sobre l’ús d’aquest potent marc Selenium anomenat POM o model d’objectes de pàgina. Ara, la pregunta sorgeix com 'Per què utilitzar POM?'.
La resposta senzilla a això és que POM és una combinació de marcs basats en dades, modulars i híbrids. És un enfocament per organitzar els scripts de manera sistemàtica de manera que faciliti al control de qualitat el manteniment del codi lliure de molèsties i també contribueixi a prevenir el codi redundant o duplicat.
Per exemple, si hi ha un canvi en el valor del localitzador en una pàgina específica, és molt fàcil identificar i fer aquest canvi ràpid només a l'script de la pàgina respectiva sense afectar el codi en cap altre lloc.
Utilitzem el concepte Model d’objectes de pàgina a Selenium Webdriver per les raons següents:
- En aquest model POM es crea un dipòsit d'objectes. És independent dels casos de prova i es pot reutilitzar per a un projecte diferent.
- La convenció de noms de mètodes és molt fàcil, comprensible i més realista.
- Sota el model d'objectes de pàgina, creem classes de pàgines que es poden reutilitzar en un altre projecte.
- El model d'objectes de pàgina és fàcil per al marc desenvolupat a causa dels seus diversos avantatges.
- En aquest model, es creen classes separades per a diferents pàgines d'una aplicació web, com ara la pàgina d'inici de sessió, la pàgina d'inici, la pàgina de detalls dels empleats, la pàgina de canvi de contrasenya, etc.
- Si hi ha algun canvi en algun element d’un lloc web, només hem de fer canvis en una classe i no en totes les classes.
- El guió dissenyat és més reutilitzable, llegible i mantenible en l'enfocament del model d'objectes de pàgina.
- La seva estructura del projecte és bastant fàcil i entenedora.
- Pot utilitzar PageFactory al model d'objectes de pàgina per tal d'inicialitzar l'element web i emmagatzemar elements a la memòria cau.
- TestNG també es pot integrar a l'enfocament Model d'objectes de pàgina.
Implementació de POM simple al seleni
# 1) Escenari per automatitzar
Ara automatitzem l’escenari donat mitjançant el Model d’objectes de pàgina.
L’escenari s’explica a continuació:
Pas 1: Inicieu el lloc 'https: //demo.vtiger.com'.
Pas 2: Introduïu la credencial vàlida.
Pas 3: Inicieu la sessió al lloc.
Pas 4: Verifiqueu la pàgina d'inici.
Pas 5: Tanqueu la sessió al lloc.
Pas 6: Tanqueu el navegador.
# 2) Scripts de seleni per a l'escenari anterior a POM
Ara creem l'estructura POM a Eclipse, tal com s'explica a continuació:
Pas 1: Creeu un projecte a Eclipse: estructura basada en POM:
a) Creeu el projecte 'Model d'objectes de pàgina'.
b) Creeu 3 paquets dins del projecte.
- biblioteca
- pàgines
- casos de prova
Biblioteca: D’aquesta manera, posem aquells codis que cal cridar una vegada i una altra en els nostres casos de prova, com ara el llançament del navegador, captures de pantalla, etc. L’usuari pot afegir-hi més classes segons la necessitat del projecte.
Pàgines: En aquest sentit, es creen classes per a cada pàgina de l'aplicació web i es poden afegir més classes de pàgina en funció del nombre de pàgines de l'aplicació.
Casos de prova: Sota això, escrivim el cas de prova d’inici de sessió i podem afegir més casos de prova segons sigui necessari per provar tota l’aplicació.
c) Les classes dels paquets es mostren a la imatge següent.
Pas 2: Creeu les classes següents al paquet de la biblioteca.
Browser.java: En aquesta classe, es defineixen 3 navegadors (Firefox, Chrome i Internet Explorer) i s’anomena en el cas de prova d’inici de sessió. En funció del requisit, l’usuari també pot provar l’aplicació en diferents navegadors.
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: En aquesta classe, s’escriu un programa de captura de pantalla i s’anomena en el cas de prova quan l’usuari vol fer una captura de pantalla de si la prova falla o passa.
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(); } } }
Pas 3: Creeu classes de pàgines a Paquet de pàgines.
HomePage.java: Aquesta és la classe de la pàgina inicial, en què es defineixen tots els elements de la pàgina inicial i els mètodes.
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: Aquesta és la classe de la pàgina d'inici de sessió, en què es defineixen tots els elements de la pàgina d'inici de sessió i els mètodes.
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(); } }
Pas 4: Creeu casos de prova per a l'escenari d'inici de sessió.
LoginTestCase.java: Aquesta és la classe LoginTestCase, on s’executa el cas de prova. L'usuari també pot crear més casos de prova segons la necessitat del projecte.
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(); } }
Pas 5: Executeu 'LoginTestCase.java'.
Pas 6: Sortida del model d'objecte de pàgina:
- Inicieu el navegador Chrome.
- El lloc web de demostració s’obre al navegador.
- Inicieu la sessió al lloc de demostració.
- Verifiqueu la pàgina d'inici.
- Tanqueu la sessió al lloc.
- Tanqueu el navegador.
Ara, explorem el concepte principal d’aquest tutorial que crida l’atenció, és a dir, 'Fàbrica de pàgines'.
Què és Pagefactory?
PageFactory és una manera d'implementar el 'Model d'objectes de pàgina'. Aquí seguim el principi de separació del dipòsit d'objectes de pàgina i els mètodes de prova. És un concepte incorporat de Model d'objectes de pàgina molt optimitzat.
Tenim ara més claredat sobre el terme Pagefactory.
# 1) En primer lloc, el concepte anomenat Pagefactory, proporciona una forma alternativa en termes de sintaxi i semàntica per crear un dipòsit d'objectes per als elements web d'una pàgina.
# 2) En segon lloc, utilitza una estratègia lleugerament diferent per a la inicialització dels elements web.
# 3) El dipòsit d'objectes per als elements web de la IU es podria crear mitjançant:
- Normal 'POM sense Pagefactory' i,
- Com a alternativa, podeu utilitzar ‘POM amb Pagefactory’.
A continuació es mostra una representació pictòrica de la mateixa:
Ara veurem tots els aspectes que diferencien el POM habitual de POM amb Pagefactory.
a) La diferència en la sintaxi de localitzar un element mitjançant POM vs POM habituals amb Pagefactory.
Per exemple , Feu clic aquí per localitzar el camp de cerca que apareix a la pàgina.
POM sense Pagefactory:
# 1) A continuació es mostra com es troba el camp de cerca mitjançant el POM habitual:
WebElement searchNSETxt=driver.findElement(By.id(“searchBox”));
# 2) El pas següent transmet el valor 'inversió' al camp Cerca NSE.
searchNSETxt.sendkeys(“investment”);
POM amb Pagefactory:
# 1) Podeu localitzar el camp de cerca mitjançant Pagefactory com es mostra a continuació.
L’anotació @FindBy s'utilitza a Pagefactory per identificar un element mentre que POM sense Pagefactory utilitza el fitxer driver.findElement () mètode per localitzar un element.
La segona afirmació de Pagefactory després @FindBy està assignant un tipus WebElement classe que funciona exactament similar a l'assignació d'un nom d'element de tipus classe WebElement com a tipus de retorn del mètode driver.findElement () que s'utilitza al POM habitual (searchNSETxt en aquest exemple).
Veurem el @FindBy anotacions detallades a la propera part d’aquest tutorial.
@FindBy(id = 'searchBox') WebElement searchNSETxt;
# 2) El pas següent passa el valor 'inversió' al camp Cerca NSE i la sintaxi continua sent la mateixa que la del POM habitual (POM sense Pagefactory).
searchNSETxt.sendkeys(“investment”);
b) La diferència en l’estratègia d’inicialització d’elements web mitjançant POM vs POM habituals amb Pagefactory.
Ús de POM sense Pagefactory:
A continuació es mostra un fragment de codi per establir la ruta del controlador de Chrome. Es crea una instància de WebDriver amb el nom controlador i ChromeDriver s’assigna al ‘controlador’. A continuació, s’utilitza el mateix objecte controlador per iniciar el lloc web de la Borsa de Valors Nacional, localitzar la caixa de cerca i introduir el valor de la cadena al camp.
El punt que vull destacar aquí és que quan es tracta de POM sense fàbrica de pàgines, la instància del controlador es crea inicialment i cada element web s’inicialitza recentment cada vegada que es fa una crida a aquest element web mitjançant driver.findElement () o driver .findElements ().
És per això que, amb un nou pas de driver.findElement () per a un element, es torna a escanejar l'estructura DOM i es fa una identificació actualitzada de l'element en aquesta pàgina.
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”);
Ús de POM amb Pagefactory:
A més d’utilitzar l’anotació @FindBy en lloc del mètode driver.findElement (), el fragment de codi següent s’utilitza addicionalment per a Pagefactory. El mètode static initElements () de la classe PageFactory s’utilitza per inicialitzar tots els elements d’interfície d’usuari de la pàgina tan bon punt es carrega la pàgina.
public PagefactoryClass(WebDriver driver) { this.driver = driver; PageFactory.initElements(driver, this); }
L’estratègia anterior fa que l’enfocament de PageFactory sigui lleugerament diferent del POM habitual. Al POM habitual, l’element web s’ha d’inicialitzar explícitament mentre que en l’enfocament de Pagefactory tots els elements s’inicialitzen amb initElements () sense inicialitzar explícitament cada element web.
Per exemple: Si el WebElement es va declarar però no es va inicialitzar al POM habitual, es llança l'error 'inicialitzar variable' o s'executa NullPointerException. Per tant, al POM habitual, cada WebElement s’ha d’inicialitzar explícitament. PageFactory té un avantatge respecte al POM habitual en aquest cas.
No inicialitzem l'element web BDate (POM sense Pagefactory), podeu veure que es mostra l'error 'Inicialitza la variable' i demana a l'usuari que l'inicialitzi a nul, de manera que no podeu suposar que els elements s'inicialitzin implícitament en localitzar-los.
Element BDate inicialitzat explícitament (POM sense Pagefactory):
Ara, vegem un parell d’instàncies d’un programa complet que utilitza PageFactory per descartar qualsevol ambigüitat en la comprensió de l’aspecte de la implementació.
Exemple 1:
- Aneu a 'http://www.nseindia.com/'
- Al menú desplegable situat al costat del camp de cerca, seleccioneu 'Derivats de divises'.
- Cerqueu 'USDINR'. Verifiqueu el text 'Dòlar americà-rupia índia - USDINR' a la pàgina resultant.
Estructura del programa:
- Es crea PagefactoryClass.java que inclou un repositori d'objectes que utilitza el concepte de fàbrica de pàgines per a nseindia.com que és un constructor per inicialitzar tots els elements web, seleccioneu mètode CurrentDerivative () per seleccionar el valor del camp desplegable del quadre de cerca, seleccioneu Símbol () per seleccionar un símbol al pàgina que apareix a continuació i verifytext () per verificar si la capçalera de la pàgina és l’esperada o no.
- NSE_MainClass.java és el fitxer de classe principal que crida a tots els mètodes anteriors i realitza les accions respectives al lloc 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 Exemple 2:
- Aneu a ‘https://www.shoppersstop.com/brands’
- Navegueu fins a l'enllaç Haute Curry.
- Verifiqueu si la pàgina Haute Curry conté el text 'Comença una cosa nova'.
Estructura del programa
- es crea shopperstopPagefactory.java que inclou un dipòsit d'objectes que utilitza el concepte pagefactory per shoppersstop.com que és un constructor per inicialitzar tots els elements web, es creen mètodes closeExtraPopup () per gestionar un quadre emergent d'alerta que s'obre, feu clic a OnHauteCurryLink () per fer clic a Haute Curry Enllaceu i verifiqueuStartNewSomething () per verificar si la pàgina Haute Curry conté el text 'Inicia alguna cosa nova'.
- Shopperstop_CallPagefactory.java és el fitxer de classe principal que crida a tots els mètodes anteriors i realitza les accions respectives al lloc 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 mitjançant la fàbrica de pàgines
Tutorials de vídeo: POM amb Page Factory
Part I
Part II
S’utilitza una classe Factory per fer que l’ús d’Objectes de pàgina sigui més senzill i senzill.
- En primer lloc, hem de trobar els elements web mitjançant anotacions @FindBy a les classes de pàgines .
- A continuació, inicialitzeu els elements mitjançant initElements () quan instancieu la classe de pàgina.
# 1) @FindBy:
L'anotació @FindBy s'utilitza a PageFactory per localitzar i declarar els elements web mitjançant diferents localitzadors.Aquí passem l’atribut i el seu valor utilitzat per localitzar l’element web a l’anotació @FindBy i es declara el WebElement.
Hi ha dues maneres d'utilitzar l'anotació.
Per exemple:
@FindBy(how = How.ID, using='EmailAddress') WebElement Email; @FindBy(id='EmailAddress') WebElement Email;
Tanmateix, la primera és la forma estàndard de declarar WebElements.
'Com' és una classe i té variables estàtiques com ID, XPATH, CLASSNAME, LINKTEXT, etc.
'utilitzant' - Per assignar un valor a una variable estàtica.
A l’anterior exemple , hem utilitzat l'atribut 'id' per localitzar l'element web 'Correu electrònic'. De la mateixa manera, podem utilitzar els següents localitzadors amb les anotacions @FindBy:
- className
- css
- nom
- xpath
- tagName
- linkText
- partialLinkText
# 2) initElements ():
Els initElements són un mètode estàtic de la classe PageFactory que s’utilitza per inicialitzar tots els elements web localitzats per l’anotació @FindBy. Per tant, instanciar les classes de pàgina fàcilment.
initElements(WebDriver driver, java.lang.Class pageObjectClass)
També hem d’entendre que POM segueix els principis d’OOPS.
- Els elements web es declaren com a variables de membre privat (ocultació de dades).
- Enllaçar WebElements amb els mètodes corresponents (Encapsulació).
Passos per crear POM mitjançant el patró de fàbrica de pàgines
# 1) Creeu un fitxer de classe Java independent per a cada pàgina web.
# 2) A cada classe, tots els elements web s'han de declarar com a variables (mitjançant anotació - @FindBy) i inicialitzar-los mitjançant el mètode initElement (). Els elements web declarats s'han d'inicialitzar per utilitzar-los en els mètodes d'acció.
# 3) Definiu els mètodes corresponents que actuïn sobre aquestes variables.
Prenguem un exemple d'un escenari senzill:
- Obriu l'URL d'una aplicació.
- Escriviu l'adreça de correu electrònic i les dades de contrasenya.
- Feu clic al botó Iniciar sessió.
- Verifiqueu el missatge d’inici de sessió correcte a la pàgina de cerca.
Capa de pàgina
Aquí tenim 2 pàgines,
- Pàgina inicial - La pàgina que s'obre quan s'introdueix l'URL i on introduïm les dades per iniciar la sessió.
- Pàgina de cerca - Una pàgina que es mostra després d'un inici de sessió correcte.
A Page Layer, cada pàgina de l'aplicació web es declara com una classe Java independent i s'hi mencionen els seus localitzadors i accions.
Passos per crear POM amb un exemple en temps real
# 1) Creeu una classe Java per a cada pàgina:
En aquest exemple , accedirem a 2 pàgines web, pàgines 'Inici' i 'Cerca'.
Per tant, crearem 2 classes Java a Page Layer (o en un paquet, com.automation.pages).
Package Name :com.automation.pages HomePage.java SearchPage.java
# 2) Definiu els elements web com a variables mitjançant Annotation @FindBy:
Estaríem interactuant amb:
- Correu electrònic, contrasenya, camp del botó d’inici de sessió a la pàgina inicial.
- Missatge correcte a la pàgina de cerca.
Per tant, definirem WebElements mitjançant @FindBy
Per exemple: Si identificarem l’adreça de correu electrònic mitjançant l’identificador d’atribut, la declaració de la seva variable és
//Locator for EmailId field @FindBy(how=How.ID,using='EmailId') private WebElementEmailIdAddress;
# 3) Creeu mètodes per a accions realitzades a WebElements.
A continuació es realitzen accions a WebElements:
- Escriviu l'acció al camp Adreça de correu electrònic.
- Escriviu l'acció al camp Contrasenya.
- Feu clic a l'acció al botó d'inici de sessió.
Per exemple, Es creen mètodes definits per l'usuari per a cada acció al WebElement com:
public void typeEmailId(String Id){ driver.findElement(EmailAddress).sendKeys(Id) }
Aquí, l'identificador es passa com a paràmetre al mètode, ja que l'usuari enviarà l'entrada des del cas de prova principal.
Nota :Cal crear un constructor a cadascuna de les classes de la capa de pàgina, per obtenir la instància del controlador de la classe principal de la capa de prova i també per inicialitzar els elements web (objectes de pàgina) declarats a la classe de pàgina mitjançant PageFactory.InitElement () .
Aquí no iniciem el controlador, sinó que la seva instància es rep de la classe principal quan es crea l'objecte de la classe de capa de pàgina.
InitElement () - s'utilitza per inicialitzar els WebElements declarats, utilitzant la instància del controlador de la classe principal. En altres paraules, els elements web es creen mitjançant la instància del controlador. Només després d'inicialitzar els WebElements, es poden utilitzar en els mètodes per realitzar accions.
Es creen dues classes Java per a cada pàgina, tal com es mostra a continuació:
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. } }
Capa de prova
Els casos de prova s’implementen en aquesta classe. Creem un paquet separat per exemple, com.automation.test i després creem una classe Java aquí (MainClass.java)
Passos per crear casos de prova:
- Inicialitzeu el controlador i obriu l'aplicació.
- Creeu un objecte de la classe PageLayer (per a cada pàgina web) i passeu la instància del controlador com a paràmetre.
- Amb l’objecte creat, feu una trucada als mètodes de la classe PageLayer (per a cada pàgina web) per tal de realitzar accions / verificació.
- Repetiu el pas 3 fins que es realitzin totes les accions i, a continuació, tanqueu el controlador.
//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(); } }
Jerarquia del tipus d’anotació que s’utilitza per declarar elements web
Les anotacions s’utilitzen per ajudar a construir una estratègia d’ubicació per als elements de la interfície d’usuari.
# 1) @FindBy
Quan es tracta de Pagefactory, @FindBy actua com una vareta màgica. Afegeix tota la potència al concepte. Ara sou conscient que l’anotació @FindBy a Pagefactory funciona igual que la del driver.findElement () al model d’objecte de pàgina habitual. S'utilitza per localitzar WebElement / WebElements amb un criteri .
# 2) @FindBys
S'utilitza per localitzar WebElement amb més d’un criteri i han de coincidir amb tots els criteris indicats. Aquests criteris s’han d’esmentar en una relació pare-fill. En altres paraules, això utilitza la relació condicional AND per localitzar els elements web utilitzant els criteris especificats. Utilitza múltiples @FindBy per definir cada criteri.
Per exemple:
Codi font HTML d'un WebElement:
A POM:
@FindBys({ @FindBy(id = 'searchId_1'), @FindBy(name = 'search_field') }) WebElementSearchButton;
A l'exemple anterior, el 'SearchButton' de WebElement només es troba si es troba coincideix amb tots dos els criteris amb un valor d'identificador 'searchId_1' i un valor de nom 'search_field'. Tingueu en compte que els primers criteris pertanyen a una etiqueta principal i el segon criteri per a una etiqueta secundària.
# 3) @FindAll
S'utilitza per localitzar WebElement amb més d’un criteri i ha de coincidir com a mínim amb un dels criteris indicats. Utilitza relacions condicionals O per localitzar WebElements. Utilitza múltiples @FindBy per definir tots els criteris.
Per exemple:
Codi font HTML:
A POM:
@FindBys({ @FindBy(id = 'UsernameNameField_1'), // doesn’t match @FindBy(name = 'User_Id') //matches @FindBy(className = “UserName_r”) //matches }) WebElementUserName;
A l'exemple anterior, el nom d'usuari de WebElement 'si es troba' coincideix amb almenys un dels criteris esmentats.
# 4) @CacheLookUp
Quan el WebElement s'utilitza més sovint en casos de prova, Selenium busca el WebElement cada cop que s'executa l'script de prova. En aquests casos, en què determinats elements web s’utilitzen globalment per a tots els TC ( Per exemple, L'escenari d'inici de sessió passa per a cada TC), aquesta anotació es pot utilitzar per mantenir aquests elements web a la memòria cau un cop es llegeixi per primera vegada.
Això, al seu torn, ajuda al codi a executar-se més ràpidament, perquè cada vegada que no ha de cercar el WebElement a la pàgina, pot obtenir la seva referència de la memòria.
Pot ser un prefix amb qualsevol de @FindBy, @FindBys i @FindAll.
Per exemple:
@CacheLookUp @FindBys({ @FindBy(id = 'UsernameNameField_1'), @FindBy(name = 'User_Id') @FindBy(className = “UserName_r”) }) WebElementUserName;
Tingueu en compte també que aquesta anotació només s’ha d’utilitzar per a elements web el valor de l’atribut (com ara xpath, nom d’identificador, nom de classe, etc.) no canvia sovint. Un cop el WebElement es troba per primera vegada, manté la seva referència a la memòria cau.
Aleshores es produeix un canvi en l’atribut de WebElement al cap de pocs dies, Selenium no podrà localitzar l’element, ja que ja té la seva referència antiga a la memòria cau i no tindrà en compte el canvi recent de WebElement.
Més informació a PageFactory.initElements ()
Ara que entenem l’estratègia de Pagefactory per inicialitzar els elements web mitjançant InitElements (), intentem comprendre les diferents versions del mètode.
El mètode que coneixem pren l’objecte controlador i l’objecte de classe actual com a paràmetres d’entrada i retorna l’objecte de pàgina inicialitzant de forma implícita i proactiva tots els elements de la pàgina.
A la pràctica, l'ús del constructor tal com es mostra a la secció anterior és més preferible que les altres formes d'ús.
Les maneres alternatives de trucar al mètode són:
# 1) En lloc d’utilitzar el punter “aquest”, podeu crear l’objecte de classe actual, passar-li la instància del controlador i cridar al mètode estàtic initElements amb paràmetres, és a dir, l’objecte del controlador i l’objecte de classe que s’acaba de crear.
public PagefactoryClass(WebDriver driver) { //version 2 PagefactoryClass page=new PagefactoryClass(driver); PageFactory.initElements(driver, page); }
# 2) La tercera manera d’inicialitzar els elements mitjançant la classe Pagefactory és mitjançant l’api anomenada “reflexió”. Sí, en lloc de crear un objecte de classe amb una paraula clau 'nova', es pot passar classname.class com a part del paràmetre d'entrada initElements ().
public PagefactoryClass(WebDriver driver) { //version 3 PagefactoryClass page=PageFactory.initElements(driver, PagefactoryClass.class); }
Preguntes freqüents
P # 1) Quines són les diferents estratègies de localització que s’utilitzen per a @FindBy?
Resposta: La resposta senzilla a això és que no hi ha estratègies de localització diferents que s’utilitzen per a @FindBy.
Utilitzen les mateixes vuit estratègies de localització que utilitza el mètode findElement () al POM habitual:
- identificador
- nom
- className
- xpath
- css
- tagName
- linkText
- partialLinkText
P # 2) Hi ha versions diferents de l'ús de les anotacions @FindBy també?
Resposta: Quan hi ha un element web que cal cercar, fem servir l’anotació @FindBy. També detallarem les formes alternatives d’utilitzar @FindBy juntament amb les diferents estratègies de localització.
Ja hem vist com s'utilitza la versió 1 de @FindBy:
@FindBy(id = 'cidkeyword') WebElement Symbol;
La versió 2 de @FindBy passa el paràmetre d’entrada com a Com i Utilitzant .
Com cerca l'estratègia de localització mitjançant la qual s'identificaria l'element web. La paraula clau utilitzant defineix el valor del localitzador.
Vegeu a continuació una millor comprensió,
- How.ID cerca l'element mitjançant identificador l'estratègia i l'element que intenta identificar té id = paraula clau.
@FindBy(how = How.ID, using = ' cidkeyword') WebElement Symbol;
- How.CLASS_NAME cerca l'element mitjançant className l'estratègia i l'element que intenta identificar té class = nova classe.
@FindBy(how = How.CLASS_NAME, using = 'newclass') WebElement Symbol;
P # 3) Hi ha alguna diferència entre les dues versions de @FindBy?
Resposta: La resposta és No, no hi ha diferències entre les dues versions. És que la primera versió és la més curta i senzilla en comparació amb la segona versió.
Q # 4) Què faig servir a la pàgina de fàbrica en cas que hi hagi una llista d'elements web que es localitzin?
Resposta: Al patró de disseny d’objectes de pàgina habitual, tenim driver.findElements () per localitzar diversos elements que pertanyen a la mateixa classe o nom d’etiqueta, però com localitzem aquests elements en el cas del model d’objectes de pàgina amb Pagefactory? La forma més senzilla d’aconseguir aquests elements és fer servir la mateixa anotació @FindBy.
Tinc entès que aquesta línia sembla ser una gran cosa per a molts de vosaltres. Però sí, és la resposta a la pregunta.
Vegem l'exemple següent:
Utilitzant el model d’objectes de pàgina habitual sense Pagefactory, utilitzeu driver.findElements per localitzar diversos elements, tal com es mostra a continuació:
private List multipleelements_driver_findelements = driver.findElements (By.class(“last”));
Es pot aconseguir el mateix utilitzant el model d'objectes de pàgina amb Pagefactory, tal com es mostra a continuació:
@FindBy (how = How.CLASS_NAME, using = 'last') private List multipleelements_FindBy;
Bàsicament, assignar els elements a una llista de tipus WebElement fa el truc independentment de si s’utilitza Pagefactory o no mentre s’identifiquen i localitzen els elements.
Q # 5) Es pot utilitzar tant el disseny d'objectes de pàgina sense pagefactory com amb Pagefactory al mateix programa?
Resposta: Sí, tant el disseny d'objectes de pàgina sense Pagefactory com amb Pagefactory es poden utilitzar al mateix programa. Podeu seguir el programa que es mostra a continuació a la pàgina Resposta per a la pregunta núm. 6 per veure com s’utilitzen tots dos al programa.
Una cosa que cal recordar és que s'hauria d'evitar el concepte Pagefactory amb la funció de memòria cau en elements dinàmics, mentre que el disseny d'objectes de pàgina funciona bé per als elements dinàmics. Tot i això, Pagefactory només s’adapta a elements estàtics.
P # 6) Hi ha maneres alternatives d'identificar elements basats en múltiples criteris?
ios preguntes i respostes d’entrevistes per a pdf amb experiència
Resposta: L’alternativa per identificar elements basats en diversos criteris és utilitzar les anotacions @FindAll i @FindBys. Aquestes anotacions ajuden a identificar elements simples o múltiples en funció dels valors obtinguts a partir dels criteris que s'hi passen.
# 1) @FindAll:
@FindAll pot contenir diversos @FindBy i retornarà tots els elements que coincideixin amb qualsevol @FindBy en una llista. @FindAll s'utilitza per marcar un camp en un objecte de pàgina per indicar que la cerca hauria d'utilitzar una sèrie d'etiquetes @FindBy. A continuació, cercarà tots els elements que coincideixin amb qualsevol dels criteris FindBy.
Tingueu en compte que no es garanteix que els elements estiguin en ordre de document.
La sintaxi per utilitzar @FindAll és la següent:
@FindAll( { @FindBy(how = How.ID, using = 'foo'), @FindBy(className = 'bar') } )
Explicació: @FindAll buscarà i identificarà elements separats conformes a cadascun dels criteris @FindBy i els enumerarà. A l'exemple anterior, primer cercarà un element amb l'id = 'foo' i, després, identificarà el segon element amb className = 'barra'.
Suposant que hi hagués un element identificat per a cada criteri FindBy, @FindAll donarà lloc a la llista de 2 elements, respectivament. Recordeu que hi pot haver diversos elements identificats per a cada criteri. Així, en paraules simples, @ Troba-ho tot actua equivalent al O operador dels criteris @FindBy aprovats.
# 2) @FindBys:
FindBys s’utilitza per marcar un camp en un objecte de pàgina per indicar que la cerca hauria d’utilitzar una sèrie d’etiquetes @FindBy en una cadena tal com es descriu a ByChained. Quan els objectes WebElement necessaris han de coincidir amb tots els criteris indicats, utilitzeu anotació @FindBys.
La sintaxi per utilitzar @FindBys és la següent:
@FindBys( { @FindBy(name=”foo”) @FindBy(className = 'bar') } )
Explicació: @FindBys cercarà i identificarà elements que compleixin tots els criteris @FindBy i els enumerarà. A l'exemple anterior, cercarà elements el nom de les quals = 'foo' i className = 'barra'.
@FindAll tindrà com a resultat la llista d'un element si suposem que hi havia un element identificat amb el nom i el className als criteris indicats.
Si no hi ha un element que compleixi totes les condicions de FindBy aprovades, el resultat de @FindBys serà zero elements. Podria haver-hi una llista d'elements web identificats si totes les condicions compleixen diversos elements. En paraules simples, @ FindBys actua equivalent al I operador dels criteris @FindBy aprovats.
Vegem la implementació de totes les anotacions anteriors mitjançant un programa detallat:
Modificarem el programa www.nseindia.com donat a la secció anterior per entendre la implementació de les anotacions @FindBy, @FindBys i @FindAll
# 1) El dipòsit d'objectes de PagefactoryClass s'actualitza de la manera següent:
Llista llista nova = driver.findElements (By.tagName (“a”));
@FindBy (com = Com. TAG_NAME , utilitzant = 'a')
privat Llista findbyvalue;
@FindAll ({ @FindBy (className = 'sel'), @FindBy (xpath = ”// a (@ id =’ tab5 ′) ”)}})
privat Llista findallvalue;
@FindBys ({ @FindBy (className = 'sel'), @FindBy (xpath = ”// a (@ id =’ tab5 ′) ”)}})
privat Llista findbysvalue;
# 2) Un nou mètode seeHowFindWorks () s'escriu a PagefactoryClass i s'invoca com l'últim mètode de la classe Main.
El mètode és el següent:
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 A continuació es mostra el resultat que es mostra a la finestra de la consola després de l'execució del programa:
Intentem comprendre el codi en detall:
# 1) Mitjançant el patró de disseny d'objectes de pàgina, l'element 'llista nova' identifica totes les etiquetes amb l'ancoratge 'a'. En altres paraules, obtenim un recompte de tots els enllaços de la pàgina.
Vam aprendre que el pagefactory @FindBy fa la mateixa feina que el driver.findElement (). L’element findbyvalue es crea per obtenir el recompte de tots els enllaços de la pàgina mitjançant una estratègia de cerca que té un concepte de fàbrica de pàgina.
Es demostra correcte que tant driver.findElement () com @FindBy fan el mateix treball i identifiquen els mateixos elements. Si mireu la captura de pantalla de la finestra de la consola resultant anterior, el recompte d’enllaços identificats amb l’element llista nova i el de findbyvalue són iguals, és a dir, 299 enllaços que es troben a la pàgina.
El resultat es va mostrar a continuació:
driver.findElements(By.tagName()) 299 count of @FindBy- list elements 299
# 2) Aquí detallem el funcionament de l’anotació @FindAll que pertany a la llista d’elements web amb el nom findallvalue.
Mirant amb profunditat cada criteri @FindBy dins de l’anotació @FindAll, el primer criteri @FindBy cerca elements amb el className = 'sel' i el segon criteri @FindBy cerca un element específic amb XPath = '// a (@ id = 'tab5')
Premeu ara F12 per inspeccionar els elements de la pàgina nseindia.com i obtenir certes claredats sobre els elements que corresponen als criteris @FindBy.
A la pàgina hi ha dos elements que corresponen a className = 'sel':
a) L'element 'Fonaments' té l'etiqueta de llista, és a dir,
amb className = 'sel'. Vegeu la instantània a continuació
b) Un altre element 'Llibre de comandes' té un XPath amb una etiqueta d'ancoratge que té el nom de la classe com a 'sel'.
c) El segon @FindBy amb XPath té una etiqueta d'ancoratge de la qual identificador és ' pestanya5 ”. Només hi ha un element identificat en resposta a la cerca que és Fonaments.
Vegeu la instantània a continuació:
Quan es va executar la prova nseindia.com, vam obtenir el recompte d'elements cercats per.
@FindAll com a 3. Els elements de findallvalue quan es mostren eren: Fonaments com el 0thelement índex, llibre de comandes com a 1celement índex i fonaments de nou com el 2ndelement índex. Ja vam saber que @FindAll identifica els elements de cada criteri @FindBy per separat.
Segons el mateix protocol, per a la cerca del primer criteri, és a dir, className = 'sel', va identificar dos elements que complien la condició i va obtenir 'Fonaments' i 'Llibre de comandes'.
Després es va passar al següent criteri @FindBy i, segons el xpath donat per al segon @FindBy, podria obtenir l’element ‘Fonaments’. Per això, finalment va identificar 3 elements, respectivament.
Per tant, no aconsegueix que els elements compleixin cap de les condicions @FindBy, sinó que tracta per separat de cadascun dels @FindBy i identifica els elements de la mateixa manera. A més, a l'exemple actual, també vam veure que no observa si els elements són únics ( Per exemple. L'element 'Fonaments' en aquest cas que es mostra dues vegades com a part del resultat dels dos criteris @FindBy)
# 3) Aquí detallem el funcionament de l’anotació @FindBys que pertany a la llista d’elements web amb el nom findbysvalue. També aquí, el primer criteri @FindBy cerca elements amb el className = 'sel' i el segon criteri @FindBy cerca un element específic amb xpath = '// a (@ id =' tab5 ').
Ara que ho sabem, els elements identificats per a la primera condició @FindBy són 'Fonaments' i 'Llibre de comandes' i el del segon criteri @FindBy és 'Fonaments'.
Llavors, en què serà diferent el resultat @FindBys que el @FindAll? A la secció anterior vam aprendre que @FindBys equival a l’operador condicional AND i, per tant, busca un element o la llista d’elements que satisfaci totes les condicions @FindBy.
Segons el nostre exemple actual, el valor 'Fonaments' és l'únic element que té class = 'sel' i id = 'tab5', de manera que compleix ambdues condicions. Per això, la mida de @FindBys a la caixa de proves és d'1 i mostra el valor com a 'Fonaments'.
Memòria cau dels elements a Pagefactory
Cada vegada que es carrega una pàgina, tots els elements de la pàgina es tornen a buscar invocant una trucada a través de @FindBy o driver.findElement () i hi ha una nova cerca dels elements a la pàgina.
La majoria de les vegades que els elements són dinàmics o continuen canviant durant el temps d'execució, sobretot si són elements AJAX, sens dubte té sentit que amb cada càrrega de pàgina hi hagi una nova cerca de tots els elements de la pàgina.
Quan la pàgina web té elements estàtics, la memòria cau de l’element pot ajudar de diverses maneres. Quan els elements estan emmagatzemats a la memòria cau, no ha de localitzar-los de nou en carregar la pàgina, sinó que pot fer referència al dipòsit d’elements emmagatzemats a la memòria cau. Això estalvia molt de temps i eleva un millor rendiment.
Pagefactory proporciona aquesta característica de guardar a la memòria cau els elements mitjançant una anotació @CacheLookUp .
L'anotació indica al controlador que utilitzi la mateixa instància del localitzador del DOM per als elements i que no els torni a cercar mentre el mètode initElements de la pàgina de fàbrica contribueix de manera destacada a emmagatzemar l'element estàtic a la memòria cau. Els initElements fan la tasca de memòria cau dels elements.
Això fa que el concepte pagefactory sigui especial sobre el patró normal de disseny d'objectes de pàgina. Ve amb els seus propis avantatges i inconvenients que parlarem una mica més endavant. Per exemple, el botó d'inici de sessió de la pàgina d'inici de Facebook és un element estàtic que es pot emmagatzemar a la memòria cau i és un element ideal per emmagatzemar-lo a la memòria cau.
Vegem ara com implementar l’anotació @CacheLookUp
Primer haureu d’importar un paquet per a Cachelookup de la manera següent:
import org.openqa.selenium.support.CacheLookup
A continuació es mostra el fragment que mostra la definició d’un element mitjançant @CacheLookUp. Tan bon punt es busca UniqueElement per primera vegada, initElement () emmagatzema la versió emmagatzemada a la memòria cau de l’element de manera que la propera vegada que el controlador no cerqui l’element es refereixi a la mateixa memòria cau i realitzi l’acció a l’element dret. de distància.
@FindBy(id = 'unique') @CacheLookup private WebElement UniqueElement;
Vegem ara a través d'un programa real de com les accions a l'element web a la memòria cau són més ràpides que a l'element web no a la memòria cau:
Millorant encara més el programa nseindia.com he escrit un altre mètode nou monitorPerformance () en el qual creo un element emmagatzemat a la memòria cau per al quadre de cerca i un element no emmagatzemat a la memòria cau per al mateix quadre de cerca.
A continuació, intento obtenir el nom de tagnet de l'element 3000 vegades tant per a l'element emmagatzemat com per a l'element no emmagatzemat, i intento mesurar el temps que ha trigat a completar la tasca tant l'element emmagatzemat com el no emmagatzemat.
M'ho he plantejat 3000 vegades, de manera que podem veure una diferència visible en els horaris dels dos. Esperaré que l'element emmagatzemat a la memòria cau hauria de completar l'obtenció del nom de marca 3000 vegades en un temps menor en comparació amb l'element que no és a la memòria cau.
Ara sabem per què l’element emmagatzemat a la memòria cau hauria de funcionar més ràpidament, és a dir, s’instrueix al controlador que no busqui l’element després de la primera cerca, sinó que continuï treballant-hi directament, i no és el cas de l’element no emmagatzemat a la memòria cau on es fa la cerca d’elements totes 3000 vegades i després es realitza l'acció sobre ell.
A continuació es mostra el codi del mètode 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'); }
En executar-lo, veurem el resultat següent a la finestra de la consola:
Segons el resultat, la tasca de l'element no emmagatzemat a la memòria cau es completa a 82 segons mentre que el temps necessari per completar la tasca a l'element emmagatzemat només era 37 segons. De fet, es tracta d’una diferència visible en el temps de resposta de l’element emmagatzemat i no emmagatzemat.
P # 7) Quins són els avantatges i els inconvenients de l’anotació @CacheLookUp al concepte Pagefactory?
Resposta:
Pros @CacheLookUp i situacions factibles per al seu ús:
@CacheLookUp és factible quan els elements són estàtics o no canvien en absolut mentre es carrega la pàgina. Aquests elements no canvien el temps d'execució. En aquests casos, és recomanable utilitzar l'anotació per millorar la velocitat general de l'execució de la prova.
Contres de l’anotació @CacheLookUp:
La desavantatge més gran de tenir elements emmagatzemats a la memòria cau és la por a obtenir StaleElementReferenceExceptions amb freqüència.
Els elements dinàmics s’actualitzen amb força freqüència amb els que són susceptibles de canviar ràpidament durant uns segons o minuts de l’interval de temps.
A continuació es mostren alguns exemples d’aquest tipus d’elements dinàmics:
- Tenir un cronòmetre a la pàgina web que permet actualitzar el temporitzador cada segon.
- Un marc que actualitza constantment l'informe meteorològic.
- Una pàgina que informa de les actualitzacions en directe de Sensex.
No són ni ideals ni factibles per a l’ús de l’anotació @CacheLookUp. Si ho feu, corre el risc d'obtenir l'excepció de StaleElementReferenceExceptions.
En emmagatzemar aquests elements a la memòria cau, durant l’execució de la prova, es modifica el DOM dels elements, però el controlador busca la versió de DOM que ja estava emmagatzemada mentre s’emmagatzemava a la memòria cau. Això fa que el controlador no pugui buscar l'element obsolet que ja no existeix a la pàgina web. És per això que es produeix StaleElementReferenceException.
Classes de fàbrica:
Pagefactory és un concepte basat en diverses interfícies i classes de fàbrica. En aquesta secció coneixerem algunes classes i interfícies de fàbrica aquí. Poques de les que veurem són AjaxElementLocatorFactory , ElementLocatorFactory i DefaultElementFactory.
Ens hem preguntat mai si Pagefactory proporciona alguna manera d’incorporar una espera implícita o explícita de l’element fins que es compleixi una determinada condició ( Exemple: Fins que un element sigui visible, activat, es pot fer clic, etc.)? Si és així, aquí teniu una resposta adequada.
AjaxElementLocatorFactory és un dels col·laboradors significatius de totes les classes de fàbrica. L’avantatge d’AjaxElementLocatorFactory és que podeu assignar un valor de temps d’espera per a un element web a la classe de pàgina Object.
Tot i que Pagefactory no proporciona una funció d’espera explícita, però, hi ha una variant per esperar implícitament amb la classe AjaxElementLocatorFactory . Aquesta classe es pot utilitzar incorporada quan l'aplicació utilitza components i elements Ajax.
A continuació s’explica com s’implementa al codi. Dins del constructor, quan fem servir el mètode initElements (), podem utilitzar AjaxElementLocatorFactory per proporcionar una espera implícita als elements.
PageFactory.initElements(driver, this); can be replaced with PageFactory.initElements( new AjaxElementLocatorFactory(driver, 20), this);
La segona línia anterior del codi implica que el controlador ha d'establir un temps d'espera de 20 segons per a tots els elements de la pàgina quan es carrega cadascun dels elements i si no es troba cap element després d'una espera de 20 segons, es llança 'NoSuchElementException' per a aquest element que falta.
També podeu definir l'espera de la manera següent:
public pageFactoryClass(WebDriver driver) { ElementLocatorFactory locateMe = new AjaxElementLocatorFactory(driver, 30); PageFactory.initElements(locateMe, this); this.driver = driver; }
El codi anterior funciona perfectament perquè la classe AjaxElementLocatorFactory implementa la interfície ElementLocatorFactory.
Aquí, la interfície pare (ElementLocatorFactory) fa referència a l’objecte de la classe fill (AjaxElementLocatorFactory). Per tant, s'utilitza el concepte Java de 'upcasting' o 'polimorfisme en temps d'execució' durant l'assignació d'un temps d'espera mitjançant AjaxElementLocatorFactory.
Pel que fa al seu funcionament tècnic, l'AjaxElementLocatorFactory crea primer un AjaxElementLocator mitjançant un SlowLoadableComponent que potser no s'ha acabat de carregar quan torna la càrrega (). Després d'una trucada a load (), el mètode isLoaded () hauria de continuar fallant fins que el component s'hagi carregat completament.
En altres paraules, tots els elements es buscaran recentment cada vegada que s’accedeixi a un element al codi invocant una trucada a locator.findElement () des de la classe AjaxElementLocator, que després aplica un temps d’espera fins a carregar-se a través de la classe SlowLoadableComponent.
A més, després d’assignar el temps d’espera mitjançant AjaxElementLocatorFactory, els elements amb l’anotació @CacheLookUp ja no es guardaran a la memòria cau, ja que l’anotació s’ignorarà.
També hi ha una variació de com tu pots trucar al initElements () mètode i com tu no hauria trucar al AjaxElementLocatorFactory per assignar el temps d'espera per a un element.
# 1) També podeu especificar un nom d'element en lloc de l'objecte controlador, tal com es mostra a continuació al mètode initElements ():
PageFactory.initElements( , this);
El mètode initElements () de la variant anterior invoca internament una trucada a la classe DefaultElementFactory i el constructor de DefaultElementFactory accepta l’objecte de la interfície SearchContext com a paràmetre d’entrada. L’objecte del controlador web i un element web pertanyen a la interfície SearchContext.
En aquest cas, el mètode initElements () inicialitzarà inicialment només l’element esmentat i no s’inicialitzaran tots els elements de la pàgina web.
# 2) Tanmateix, aquí hi ha un gir interessant d’aquest fet que afirma com no s’ha de trucar a l’objecte AjaxElementLocatorFactory d’una manera específica. Si faig servir la variant anterior de initElements () juntament amb AjaxElementLocatorFactory, fallarà.
Exemple: El codi següent, és a dir, passar el nom de l’element en lloc de l’objecte controlador a la definició AjaxElementLocatorFactory no funcionarà com a constructor de la classe AjaxElementLocatorFactory només pren l’objecte controlador web com a paràmetre d’entrada i, per tant, l’objecte SearchContext amb element web no funcionaria.
PageFactory.initElements(new AjaxElementLocatorFactory(, 10), this);
Q # 8) L'ús de la fàbrica de pàgina és una opció factible sobre el patró de disseny d'objectes de pàgina normal?
Resposta: Aquesta és la pregunta més important que la gent té i per això vaig pensar a abordar-la al final del tutorial. Ara coneixem el 'entrar i sortir' de Pagefactory a partir dels seus conceptes, anotacions utilitzades, funcions addicionals que admet, implementació mitjançant codi, els avantatges i els contres.
Tot i això, ens quedem amb aquesta pregunta essencial que, si pagefactory té tantes coses bones, per què no ens quedem amb el seu ús.
Pagefactory ve amb el concepte de CacheLookUp, que hem vist que no és factible per a elements dinàmics, com ara els valors de l’element que s’actualitzen sovint. Per tant, pagefactory sense CacheLookUp, és una bona opció? Sí, si els xpaths són estàtics.
Tanmateix, el desavantatge és que l'aplicació de l'edat moderna està plena d'elements dinàmics pesats on sabem que el disseny d'objectes de pàgina sense que pagefactory funcioni bé, però el concepte pagefactory funciona igual de bé amb xpaths dinàmics? Potser no. Aquí hi ha un exemple ràpid:
A la pàgina web de nseindia.com, veiem una taula com es mostra a continuació.
El xpath de la taula és
'//*(@id='tab9Content')/table/tbody/tr(+count+)/td(1)'
Volem recuperar valors de cada fila per a la primera columna 'Compra quantitat'. Per fer-ho, haurem d’incrementar el comptador de files, però l’índex de columna es mantindrà 1. No hi ha manera que puguem passar aquest XPath dinàmic a l’anotació @FindBy, ja que l’anotació accepta valors estàtics i no es pot transmetre cap variable això.
Aquí és on la fàbrica de pàgina falla completament mentre el POM habitual funciona amb ell. Podeu utilitzar fàcilment un bucle for per incrementar l’índex de files mitjançant xpaths dinàmics al mètode driver.findElement ().
Conclusió
El model d'objectes de pàgina és un concepte o patró de disseny utilitzat en el marc d'automatització de Selenium.
La convecció de noms de mètodes és fàcil d'utilitzar al Model d'objectes de pàgina. El codi a POM és fàcil d’entendre, es pot reutilitzar i mantenir. A POM, si hi ha algun canvi a l'element web, n'hi ha prou amb fer els canvis a la seva classe respectiva, en lloc d'editar totes les classes.
Pagefactory, igual que el POM habitual, és un concepte meravellós d’aplicació. Tot i això, hem de saber on és factible el POM habitual i on s’adapta bé la Pagefactory. A les aplicacions estàtiques (on XPath i els elements són estàtics), Pagefactory es pot implementar de forma general amb avantatges addicionals de millor rendiment.
Com a alternativa, quan l’aplicació inclou elements tant dinàmics com estàtics, és possible que tingueu una implementació mixta del pom amb Pagefactory i sense Pagefactory, segons la viabilitat de cada element web.
Autor: Aquest tutorial ha estat escrit per Shobha D. Treballa com a cap de projecte i compta amb més de 9 anys d’experiència en proves manuals, d’automatització (Selenium, IBM Rational Functional Tester, Java) i API (SOAPUI i tranquil·litat a Java) .
Ara us dirigiu a vosaltres, per a la implementació posterior de Pagefactory.
Feliç explorant !!!
=> Visiteu aquí per aprendre el seleni des de zero.
Lectura recomanada
- 30+ millors tutorials sobre seleni: apreneu el seleni amb exemples reals
- Escenaris de scripts i resolució de problemes de Selenium eficients: tutorial núm. 27 de Selenium
- Depuració d’escriptures de Selenium amb registres (Tutorial Log4j) - Tutorial Selenium núm. 26
- Introducció a JUnit Framework i el seu ús a Selenium Script - Selenium Tutorial # 11
- 7 factors que afecten l'estimació de proves del projecte d'automatització de Selenium - Tutorial Selenium # 32
- Afirmacions en seleni mitjançant marcs Junit i TestNG
- Com s'utilitza el marc TestNG per crear scripts de Selenium - Tutorial # 12 de TestNG Selenium
- Més informació sobre com s'utilitzen les anotacions TestNG al seleni (amb exemples)