page object model with page factory selenium tutorial
Questo tutorial approfondito spiega tutto su Page Object Model (POM) con Pagefactory utilizzando esempi. Puoi anche imparare l'implementazione di POM in selenio:
In questo tutorial, capiremo come creare un modello di oggetti di pagina utilizzando l'approccio di Page Factory. Ci concentreremo su:
- Classe di fabbrica
- Come creare un POM di base utilizzando il pattern Page Factory
- Annotazioni diverse utilizzate nell'approccio Page Factory
Prima di vedere cos'è Pagefactory e come può essere utilizzato insieme al modello a oggetti Page, capiamo cos'è il Page Object Model che è comunemente noto come POM.
=> Visita qui per vedere la serie di formazione sul selenio per tutti.
Cosa imparerai:
- Cos'è il Page Object Model (POM)?
- Cos'è Pagefactory?
- POM utilizzando Page Factory
- Esercitazioni video - POM con Page Factory
- Passaggi per creare POM utilizzando il pattern Page Factory
- Livello pagina
- Passaggi per creare POM con esempio in tempo reale
- Livello di prova
- Gerarchia dei tipi di annotazione utilizzata per la dichiarazione di WebElements
- Altro su PageFactory.initElements ()
- Domande frequenti
- Conclusione
Cos'è il Page Object Model (POM)?
Le terminologie teoriche descrivono il Modello a oggetti della pagina come modello di progettazione utilizzato per creare un repository di oggetti per gli elementi Web disponibili nell'applicazione in prova. Pochi altri si riferiscono ad esso come a un framework per l'automazione Selenium per l'applicazione in esame.
Tuttavia, quello che ho capito sul termine Page Object Model è:
# 1) Si tratta di un modello di progettazione in cui si dispone di un file di classe Java separato corrispondente a ciascuna schermata o pagina dell'applicazione. Il file di classe potrebbe includere il repository di oggetti degli elementi dell'interfaccia utente nonché i metodi.
#Due) Nel caso in cui ci siano elementi web enormi su una pagina, la classe del repository di oggetti per una pagina può essere separata dalla classe che include i metodi per la pagina corrispondente.
Esempio: Se la pagina Registra account ha molti campi di input, potrebbe esserci una classe RegisterAccountObjects.java che forma l'archivio oggetti per gli elementi dell'interfaccia utente nella pagina di registrazione degli account.
È possibile creare un file di classe separato RegisterAccount.java che estende o eredita RegisterAccountObjects che include tutti i metodi che eseguono azioni diverse sulla pagina.
# 3) Inoltre, potrebbe esserci un pacchetto generico con un file {roperties, dati di test Excel e metodi comuni sotto un pacchetto.
Esempio: DriverFactory che potrebbe essere utilizzato molto facilmente in tutte le pagine dell'applicazione
Capire POM con l'esempio
Dai un'occhiata Qui per saperne di più su POM.
Di seguito è riportata un'istantanea della pagina Web:
Facendo clic su ciascuno di questi collegamenti reindirizzerà l'utente a una nuova pagina.
Ecco l'istantanea di come viene costruita la struttura del progetto con Selenium utilizzando il modello a oggetti Page corrispondente a ciascuna pagina del sito web. Ogni classe Java include un repository di oggetti e metodi per eseguire diverse azioni all'interno della pagina.
Inoltre, ci sarà un altro JUNIT o TestNG o un file di classe Java che invoca chiamate ai file di classe di queste pagine.
Perché utilizziamo il modello a oggetti della pagina?
C'è un brusio sull'uso di questo potente framework Selenium chiamato POM o modello di oggetti di pagina. Ora, sorge la domanda: 'Perché usare POM?'.
La risposta semplice a questa domanda è che POM è una combinazione di framework basati sui dati, modulari e ibridi. È un approccio per organizzare sistematicamente gli script in modo tale da rendere facile per il QA mantenere il codice senza problemi e aiuta anche a prevenire il codice ridondante o duplicato.
Ad esempio, se c'è una modifica nel valore del localizzatore su una pagina specifica, è molto facile identificare e apportare quella modifica rapida solo nello script della rispettiva pagina senza influire sul codice altrove.
Usiamo il concetto di Page Object Model in Selenium Webdriver per i seguenti motivi:
- Un repository di oggetti viene creato in questo modello POM. È indipendente dai casi di test e può essere riutilizzato per un progetto diverso.
- La convenzione di denominazione dei metodi è molto semplice, comprensibile e più realistica.
- Sotto il modello a oggetti Page, creiamo classi di pagina che possono essere riutilizzate in un altro progetto.
- Il modello a oggetti Page è facile per il framework sviluppato grazie ai suoi numerosi vantaggi.
- In questo modello, vengono create classi separate per diverse pagine di un'applicazione Web come la pagina di accesso, la home page, la pagina dei dettagli del dipendente, la pagina di modifica della password, ecc.
- Se viene apportata una modifica a qualsiasi elemento di un sito Web, è necessario apportare modifiche solo in una classe e non in tutte le classi.
- Lo script progettato è più riutilizzabile, leggibile e gestibile nell'approccio del modello a oggetti della pagina.
- La sua struttura del progetto è abbastanza semplice e comprensibile.
- Può usare PageFactory nel modello a oggetti della pagina per inizializzare l'elemento web e memorizzare gli elementi nella cache.
- TestNG può anche essere integrato nell'approccio Page Object Model.
Implementazione di POM semplice in selenio
# 1) Scenario da automatizzare
Ora automatizziamo lo scenario dato usando il Page Object Model.
Lo scenario è spiegato di seguito:
Passo 1: Avvia il sito 'https: //demo.vtiger.com'.
Passo 2: Immettere la credenziale valida.
Passaggio 3: Accedi al sito.
Passaggio 4: Verifica la home page.
Passaggio 5: Esci dal sito.
Passaggio 6: Chiudi il browser.
# 2) Script di selenio per lo scenario precedente in POM
Ora creiamo la struttura POM in Eclipse, come spiegato di seguito:
Passo 1: Crea un progetto in Eclipse - Struttura basata su POM:
a) Creare il progetto 'Modello oggetto pagina'.
b) Creare 3 pacchetti nell'ambito del progetto.
- biblioteca
- pagine
- casi test
Biblioteca: Sotto questo, mettiamo quei codici che devono essere chiamati più e più volte nei nostri casi di test come Avvio del browser, Screenshot, ecc. L'utente può aggiungere più classi sotto di esso in base alle necessità del progetto.
Pagine: Sotto questo, le classi vengono create per ogni pagina nell'applicazione web e possono aggiungere più classi di pagina in base al numero di pagine nell'applicazione.
Casi test: Sotto questo, scriviamo il caso di test di accesso e possiamo aggiungere altri casi di test come richiesto per testare l'intera applicazione.
c) Le classi sotto i Pacchetti sono mostrate nell'immagine sottostante.
Passo Due: Crea le seguenti classi nel pacchetto della libreria.
Browser.java: In questa classe sono definiti 3 browser (Firefox, Chrome e Internet Explorer) e viene chiamato nel caso di test di accesso. In base al requisito, l'utente può testare l'applicazione anche in diversi browser.
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: In questa classe, viene scritto un programma di screenshot e viene chiamato nel caso di test quando l'utente desidera acquisire uno screenshot per verificare se il test ha esito negativo o superato.
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(); } } }
Passaggio 3: Crea classi di pagina sotto Pacchetto di pagine.
HomePage.java: Questa è la classe Home page, in cui sono definiti tutti gli elementi della home page e dei metodi.
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: Questa è la classe della pagina di accesso, in cui sono definiti tutti gli elementi della pagina di accesso e dei metodi.
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(); } }
Passaggio 4: Crea casi di test per lo scenario di accesso.
LoginTestCase.java: Questa è la classe LoginTestCase, in cui viene eseguito il test case. L'utente può anche creare più casi di test secondo le necessità del progetto.
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(); } }
Passaggio 5: Eseguire 'LoginTestCase.java'.
Passaggio 6: Output del modello a oggetti della pagina:
- Avvia il browser Chrome.
- Il sito Web dimostrativo viene aperto nel browser.
- Accedi al sito demo.
- Verifica la home page.
- Esci dal sito.
- Chiudi il browser.
Ora, esploriamo il concetto principale di questo tutorial che attira l'attenzione, ad es. 'Pagefactory'.
Cos'è Pagefactory?
PageFactory è un modo per implementare il 'Page Object Model'. Qui seguiamo il principio di separazione del repository degli oggetti della pagina e dei metodi di test. È un concetto integrato di Page Object Model che è molto ottimizzato.
Cerchiamo ora di avere più chiarezza sul termine Pagefactory.
# 1) In primo luogo, il concetto chiamato Pagefactory, fornisce un modo alternativo in termini di sintassi e semantica per creare un repository di oggetti per gli elementi web su una pagina.
#Due) In secondo luogo, utilizza una strategia leggermente diversa per l'inizializzazione degli elementi web.
# 3) Il repository di oggetti per gli elementi web dell'interfaccia utente potrebbe essere costruito utilizzando:
- Solita 'POM senza Pagefactory' e,
- In alternativa, puoi utilizzare 'POM con Pagefactory'.
Di seguito è riportata una rappresentazione pittorica dello stesso:
Ora vedremo tutti gli aspetti che differenziano il solito POM da POM con Pagefactory.
a) La differenza nella sintassi di localizzazione di un elemento utilizzando il solito POM vs POM con Pagefactory.
Per esempio , Fare clic su Qui per individuare il campo di ricerca visualizzato nella pagina.
POM senza Pagefactory:
# 1) Di seguito è riportato come individuare il campo di ricerca utilizzando il solito POM:
WebElement searchNSETxt=driver.findElement(By.id(“searchBox”));
# 2) Il passaggio seguente trasferisce il valore 'investimento' nel campo Cerca NSE.
searchNSETxt.sendkeys(“investment”);
POM utilizzando Pagefactory:
# 1) È possibile individuare il campo di ricerca utilizzando Pagefactory come mostrato di seguito.
L'annotazione @FindBy viene utilizzato in Pagefactory per identificare un elemento mentre POM senza Pagefactory utilizza l'estensione driver.findElement () metodo per individuare un elemento.
La seconda dichiarazione per Pagefactory dopo @FindBy sta assegnando un di tipo WebElement classe che funziona esattamente in modo simile all'assegnazione di un nome di elemento di tipo WebElement class come tipo restituito del metodo driver.findElement () che viene utilizzato nel solito POM (searchNSETxt in questo esempio).
Guarderemo il file @FindBy annotazioni in dettaglio nella parte successiva di questo tutorial.
@FindBy(id = 'searchBox') WebElement searchNSETxt;
#Due) Il passaggio seguente trasferisce il valore 'investimento' nel campo Cerca NSE e la sintassi rimane la stessa di quella del solito POM (POM senza Pagefactory).
searchNSETxt.sendkeys(“investment”);
b) La differenza nella strategia di inizializzazione degli elementi Web utilizzando il solito POM vs POM con Pagefactory.
Utilizzo di POM senza Pagefactory:
Di seguito è riportato uno snippet di codice per impostare il percorso del driver Chrome. Viene creata un'istanza WebDriver con il nome driver e ChromeDriver viene assegnato al 'driver'. Lo stesso oggetto driver viene quindi utilizzato per avviare il sito Web della Borsa Valori, individuare la casella di ricerca e immettere il valore della stringa nel campo.
Il punto che desidero evidenziare qui è che quando è POM senza page factory, l'istanza del driver viene creata inizialmente e ogni elemento web viene inizializzato di recente ogni volta che c'è una chiamata a quell'elemento web usando driver.findElement () o driver .findElements ().
Questo è il motivo per cui, con un nuovo passaggio di driver.findElement () per un elemento, la struttura DOM viene nuovamente esaminata e l'identificazione aggiornata dell'elemento viene eseguita su quella pagina.
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”);
Utilizzo di POM con Pagefactory:
Oltre a utilizzare l'annotazione @FindBy invece del metodo driver.findElement (), lo snippet di codice seguente viene utilizzato in aggiunta per Pagefactory. Il metodo statico initElements () della classe PageFactory viene utilizzato per inizializzare tutti gli elementi dell'interfaccia utente sulla pagina non appena la pagina viene caricata.
public PagefactoryClass(WebDriver driver) { this.driver = driver; PageFactory.initElements(driver, this); }
La strategia di cui sopra rende l'approccio di PageFactory leggermente diverso dal solito POM. Nel solito POM, l'elemento web deve essere inizializzato esplicitamente mentre nell'approccio Pagefactory tutti gli elementi sono inizializzati con initElements () senza inizializzare esplicitamente ogni elemento web.
Per esempio: Se il WebElement è stato dichiarato ma non inizializzato nel solito POM, viene generato l'errore 'inizializza variabile' o NullPointerException. Quindi nel solito POM, ogni WebElement deve essere inizializzato esplicitamente. PageFactory in questo caso ha un vantaggio rispetto al solito POM.
Cerchiamo di non inizializzare l'elemento web BDate (POM senza Pagefactory), puoi vedere che l'errore 'Inizializza variabile' viene visualizzato e richiede all'utente di inizializzarlo su null, quindi non puoi presumere che gli elementi vengano inizializzati implicitamente quando li individuano.
Element BDate esplicitamente inizializzato (POM senza Pagefactory):
Ora, diamo un'occhiata a un paio di istanze di un programma completo che utilizza PageFactory per escludere qualsiasi ambiguità nella comprensione dell'aspetto dell'implementazione.
Esempio 1:
- Vai a 'http://www.nseindia.com/'
- Dal menu a discesa accanto al campo di ricerca, seleziona 'Currency Derivatives'.
- Cerca 'USDINR'. Verifica il testo 'Dollaro statunitense-Rupia indiana - USDINR' nella pagina risultante.
Struttura del programma:
- Viene creato PagefactoryClass.java che include un repository di oggetti utilizzando il concetto di fabbrica di pagine per nseindia.com che è un costruttore per inizializzare tutti gli elementi web, metodo selectCurrentDerivative () per selezionare il valore dal campo a discesa Casella di ricerca, selectSymbol () per selezionare un simbolo sul pagina che viene visualizzata successivamente e verifytext () per verificare se l'intestazione della pagina è come previsto o meno.
- NSE_MainClass.java è il file di classe principale che chiama tutti i metodi precedenti ed esegue le rispettive azioni sul sito 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 Esempio 2:
- Vai a 'https://www.shoppersstop.com/brands'
- Vai al link Haute curry.
- Verifica se la pagina Haute Curry contiene il testo 'Inizia qualcosa di nuovo'.
Struttura del programma
- shopperstopPagefactory.java che include un repository di oggetti utilizzando il concetto pagefactory per shoppersstop.com che è un costruttore per inizializzare tutti gli elementi web viene creato, metodi closeExtraPopup () per gestire una finestra pop-up di avviso che si apre, fare clic su OnHauteCurryLink () per fare clic su Haute Curry Collega e verificaStartNewSomething () per verificare se la pagina Haute Curry contiene il testo 'Inizia qualcosa di nuovo'.
- Shopperstop_CallPagefactory.java è il file di classe principale che chiama tutti i metodi precedenti ed esegue le rispettive azioni sul sito 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 utilizzando Page Factory
Esercitazioni video - POM con Page Factory
Parte I
Seconda parte
Una classe Factory viene utilizzata per rendere l'uso degli oggetti pagina più semplice e facile.
- Innanzitutto, dobbiamo trovare gli elementi web per annotazione @FindBy nelle classi di pagina .
- Quindi inizializza gli elementi utilizzando initElements () durante la creazione di un'istanza della classe della pagina.
# 1) @FindBy:
L'annotazione @FindBy viene utilizzata in PageFactory per individuare e dichiarare gli elementi Web utilizzando diversi locatori.Qui, passiamo l'attributo e il suo valore utilizzato per individuare l'elemento web all'annotazione @FindBy e quindi viene dichiarato WebElement.
Esistono 2 modi in cui è possibile utilizzare l'annotazione.
Per esempio:
@FindBy(how = How.ID, using='EmailAddress') WebElement Email; @FindBy(id='EmailAddress') WebElement Email;
Tuttavia, il primo è il modo standard per dichiarare WebElements.
'Come' è una classe e ha variabili statiche come ID, XPATH, CLASSNAME, LINKTEXT, ecc.
'Utilizzando' - Per assegnare un valore a una variabile statica.
In quanto sopra esempio , abbiamo utilizzato l'attributo 'id' per individuare l'elemento web 'Email'. Allo stesso modo, possiamo usare i seguenti localizzatori con le annotazioni @FindBy:
- nome della classe
- css
- nome
- xpath
- tagName
- linkText
- partialLinkText
# 2) initElements ():
InitElements è un metodo statico della classe PageFactory che viene utilizzato per inizializzare tutti gli elementi web individuati dall'annotazione @FindBy. Così, istanziando facilmente le classi Page.
initElements(WebDriver driver, java.lang.Class pageObjectClass)
Dovremmo anche capire che POM segue i principi OOPS.
- Gli elementi Web sono dichiarati come variabili membro private (Nascondere dati).
- Associazione di WebElements con metodi corrispondenti (incapsulamento).
Passaggi per creare POM utilizzando il pattern Page Factory
# 1) Crea un file di classe Java separato per ogni pagina web.
#Due) In ogni classe, tutti i WebElements dovrebbero essere dichiarati come variabili (usando annotation - @FindBy) e inizializzati usando il metodo initElement (). Gli elementi Web dichiarati devono essere inizializzati per essere utilizzati nei metodi di azione.
# 3) Definire i metodi corrispondenti che agiscono su quelle variabili.
Facciamo un esempio di uno scenario semplice:
- Apri l'URL di un'applicazione.
- Digitare i dati dell'indirizzo e-mail e della password.
- Fare clic sul pulsante Accedi.
- Verifica il messaggio di accesso riuscito nella pagina di ricerca.
Livello pagina
Qui abbiamo 2 pagine,
- HomePage - La pagina che si apre quando viene inserito l'URL e dove inseriamo i dati per il login.
- SearchPage - Una pagina che viene visualizzata dopo un accesso riuscito.
In Page Layer, ogni pagina nell'applicazione Web è dichiarata come una classe Java separata e i suoi localizzatori e azioni sono menzionati lì.
Passaggi per creare POM con esempio in tempo reale
# 1) Crea una classe Java per ogni pagina:
In questo esempio , accediamo a 2 pagine web, 'Home' e 'Cerca'.
Quindi, creeremo 2 classi Java in Page Layer (o in un pacchetto diciamo, com.automation.pages).
Package Name :com.automation.pages HomePage.java SearchPage.java
# 2) Definisci gli elementi Web come variabili utilizzando Annotation @FindBy:
Interageremmo con:
- E-mail, password, campo del pulsante di accesso nella home page.
- Messaggio di successo nella pagina di ricerca.
Quindi definiremo WebElements usando @FindBy
Per esempio: Se dobbiamo identificare EmailAddress utilizzando l'attributo id, la sua dichiarazione di variabile è
//Locator for EmailId field @FindBy(how=How.ID,using='EmailId') private WebElementEmailIdAddress;
# 3) Crea metodi per le azioni eseguite su WebElements.
Le seguenti azioni vengono eseguite su WebElements:
- Digita l'azione nel campo Indirizzo e-mail.
- Digita l'azione nel campo Password.
- Fare clic sull'azione sul pulsante di accesso.
Per esempio, I metodi definiti dall'utente vengono creati per ogni azione su WebElement come,
public void typeEmailId(String Id){ driver.findElement(EmailAddress).sendKeys(Id) }
Qui, l'Id viene passato come parametro nel metodo, poiché l'input verrà inviato dall'utente dal caso di test principale.
Nota :È necessario creare un costruttore in ciascuna delle classi nel Page Layer, al fine di ottenere l'istanza del driver dalla classe Main in Test Layer e anche per inizializzare WebElements (Page Objects) dichiarati nella classe della pagina utilizzando PageFactory.InitElement () .
Non iniziamo il driver qui, piuttosto la sua istanza viene ricevuta dalla Main Class quando viene creato l'oggetto della classe Page Layer.
InitElement () - viene utilizzato per inizializzare i WebElements dichiarati, utilizzando l'istanza del driver dalla classe principale. In altre parole, gli elementi Web vengono creati utilizzando l'istanza del driver. Solo dopo che gli elementi Web sono stati inizializzati, possono essere utilizzati nei metodi per eseguire azioni.
Vengono create due classi Java per ogni pagina come mostrato di seguito:
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. } }
Livello di prova
I casi di test sono implementati in questa classe. Creiamo un pacchetto separato diciamo, com.automation.test e quindi creiamo una classe Java qui (MainClass.java)
Passaggi per creare casi di test:
- Inizializza il driver e apri l'applicazione.
- Crea un oggetto della classe PageLayer (per ogni pagina web) e passa l'istanza del driver come parametro.
- Utilizzando l'oggetto creato, effettuare una chiamata ai metodi nella classe PageLayer (per ogni pagina web) per eseguire azioni / verifica.
- Ripetere il passaggio 3 fino a quando non vengono eseguite tutte le azioni, quindi chiudere il driver.
//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(); } }
Gerarchia dei tipi di annotazione utilizzata per dichiarare gli elementi Web
Le annotazioni vengono utilizzate per creare una strategia di localizzazione per gli elementi dell'interfaccia utente.
# 1) @FindBy
Quando si tratta di Pagefactory, @FindBy agisce come una bacchetta magica. Aggiunge tutta la potenza al concetto. Ora sei consapevole che l'annotazione @FindBy in Pagefactory esegue la stessa operazione di driver.findElement () nel solito modello di oggetti di pagina. Viene utilizzato per individuare WebElement / WebElements con un criterio .
# 2) @FindBys
Viene utilizzato per individuare WebElement con più di un criterio e devono corrispondere a tutti i criteri forniti. Questi criteri dovrebbero essere menzionati in una relazione genitore-figlio. In altre parole, utilizza la relazione condizionale AND per individuare gli elementi Web utilizzando i criteri specificati. Utilizza più @FindBy per definire ogni criterio.
Per esempio:
Codice sorgente HTML di un WebElement:
In POM:
@FindBys({ @FindBy(id = 'searchId_1'), @FindBy(name = 'search_field') }) WebElementSearchButton;
Nell'esempio precedente, il 'Pulsante di ricerca' di WebElement si trova solo se esso corrisponde a entrambi i criteri il cui valore id è 'searchId_1' e il valore del nome è 'search_field'. Tieni presente che il primo criterio appartiene a un tag principale e il secondo a un tag figlio.
# 3) @FindAll
Viene utilizzato per individuare WebElement con più di un criterio e deve corrispondere ad almeno uno dei criteri dati. Questo utilizza relazioni condizionali OR per individuare WebElements. Utilizza più @FindBy per definire tutti i criteri.
Per esempio:
Codice sorgente HTML:
In POM:
@FindBys({ @FindBy(id = 'UsernameNameField_1'), // doesn’t match @FindBy(name = 'User_Id') //matches @FindBy(className = “UserName_r”) //matches }) WebElementUserName;
Nell'esempio precedente, il nome utente di WebElement si trova se esso corrisponde ad almeno uno dei criteri citati.
# 4) @CacheLookUp
Quando WebElement viene utilizzato più spesso nei casi di test, Selenium cerca WebElement ogni volta che viene eseguito lo script di test. In quei casi, in cui alcuni WebElement sono utilizzati globalmente per tutti i TC ( Per esempio, Lo scenario di accesso si verifica per ogni TC), questa annotazione può essere utilizzata per mantenere quei WebElement nella memoria cache una volta letti per la prima volta.
Questo, a sua volta, aiuta il codice a essere eseguito più velocemente perché ogni volta non deve cercare il WebElement nella pagina, ma può ottenere il suo riferimento dalla memoria.
Può essere un prefisso con uno qualsiasi di @FindBy, @FindBys e @FindAll.
Per esempio:
@CacheLookUp @FindBys({ @FindBy(id = 'UsernameNameField_1'), @FindBy(name = 'User_Id') @FindBy(className = “UserName_r”) }) WebElementUserName;
Si noti inoltre che questa annotazione dovrebbe essere utilizzata solo per WebElements il cui valore di attributo (come xpath, id name, class name, ecc.) Non cambia abbastanza spesso. Una volta che WebElement viene individuato per la prima volta, mantiene il suo riferimento nella memoria cache.
Quindi, dopo alcuni giorni si verifica un cambiamento nell'attributo di WebElement, Selenium non sarà in grado di individuare l'elemento, perché ha già il suo vecchio riferimento nella sua memoria cache e non prenderà in considerazione la recente modifica in WebElement.
Altro su PageFactory.initElements ()
Ora che abbiamo compreso la strategia di Pagefactory sull'inizializzazione degli elementi web utilizzando InitElements (), proviamo a capire le diverse versioni del metodo.
Il metodo come sappiamo prende l'oggetto driver e l'oggetto classe corrente come parametri di input e restituisce l'oggetto pagina inizializzando in modo implicito e proattivo tutti gli elementi sulla pagina.
In pratica, l'uso del costruttore come mostrato nella sezione precedente è più preferibile rispetto alle altre modalità del suo utilizzo.
I modi alternativi per chiamare il metodo sono:
# 1) Invece di utilizzare il puntatore 'this', è possibile creare l'oggetto classe corrente, passarvi l'istanza del driver e chiamare il metodo statico initElements con parametri, ad esempio l'oggetto driver e l'oggetto classe che è stato appena creato.
public PagefactoryClass(WebDriver driver) { //version 2 PagefactoryClass page=new PagefactoryClass(driver); PageFactory.initElements(driver, page); }
#Due) Il terzo modo per inizializzare gli elementi usando la classe Pagefactory è usare l'API chiamata 'reflection'. Sì, invece di creare un oggetto classe con una parola chiave 'new', classname.class può essere passato come parte del parametro di input initElements ().
public PagefactoryClass(WebDriver driver) { //version 3 PagefactoryClass page=PageFactory.initElements(driver, PagefactoryClass.class); }
Domande frequenti
D # 1) Quali sono le diverse strategie di localizzazione utilizzate per @FindBy?
Risposta: La semplice risposta a questa domanda è che non esistono diverse strategie di localizzazione utilizzate per @FindBy.
Usano le stesse 8 strategie di localizzazione che il metodo findElement () nel solito POM usa:
- id
- nome
- nome della classe
- xpath
- css
- tagName
- linkText
- partialLinkText
D # 2) Esistono versioni differenti anche per l'utilizzo delle annotazioni @FindBy?
Risposta: Quando c'è un elemento web da cercare, usiamo l'annotazione @FindBy. Elaboreremo i modi alternativi di utilizzare @FindBy insieme alle diverse strategie di localizzazione.
Abbiamo già visto come utilizzare la versione 1 di @FindBy:
@FindBy(id = 'cidkeyword') WebElement Symbol;
La versione 2 di @FindBy passa il parametro di input come Come e Utilizzando .
Come cerca la strategia di localizzazione utilizzando la quale sarebbe identificato il webelement. La parola chiave utilizzando definisce il valore del localizzatore.
Vedi sotto per una migliore comprensione,
- How.ID cerca l'elemento utilizzando id strategia e l'elemento che cerca di identificare ha id = cidkeyword.
@FindBy(how = How.ID, using = ' cidkeyword') WebElement Symbol;
- How.CLASS_NAME cerca l'elemento utilizzando nome della classe la strategia e l'elemento che cerca di identificare ha class = newclass.
@FindBy(how = How.CLASS_NAME, using = 'newclass') WebElement Symbol;
D # 3) C'è una differenza tra le due versioni di @FindBy?
Risposta: La risposta è No, non c'è differenza tra le due versioni. È solo che la prima versione è la più breve e più facile rispetto alla seconda versione.
D # 4) Cosa devo usare in pagefactory nel caso in cui ci sia un elenco di elementi web da individuare?
Risposta: Nel solito modello di progettazione degli oggetti di pagina, abbiamo driver.findElements () per individuare più elementi appartenenti alla stessa classe o nome di tag, ma come individuare tali elementi nel caso del modello di oggetti di pagina con Pagefactory? Il modo più semplice per ottenere tali elementi è utilizzare la stessa annotazione @FindBy.
Capisco che questa frase sembra essere un grattacapo per molti di voi. Ma sì, è la risposta alla domanda.
Diamo un'occhiata all'esempio seguente:
Utilizzando il solito modello di oggetti di pagina senza Pagefactory, si utilizza driver.findElements per individuare più elementi come mostrato di seguito:
private List multipleelements_driver_findelements = driver.findElements (By.class(“last”));
Lo stesso può essere ottenuto utilizzando il modello a oggetti della pagina con Pagefactory come indicato di seguito:
@FindBy (how = How.CLASS_NAME, using = 'last') private List multipleelements_FindBy;
Fondamentalmente, l'assegnazione degli elementi a un elenco di tipo WebElement fa il trucco indipendentemente dal fatto che Pagefactory sia stato utilizzato o meno durante l'identificazione e l'individuazione degli elementi.
D # 5) È possibile utilizzare sia il design dell'oggetto Page senza pagefactory che con Pagefactory nello stesso programma?
Risposta: Sì, sia il design dell'oggetto di pagina senza Pagefactory che con Pagefactory possono essere utilizzati nello stesso programma. Puoi seguire il programma indicato di seguito in Risposta alla domanda n. 6 per vedere come vengono utilizzati entrambi nel programma.
Una cosa da ricordare è che il concetto di Pagefactory con la funzionalità cache dovrebbe essere evitato sugli elementi dinamici mentre il design degli oggetti di pagina funziona bene per gli elementi dinamici. Tuttavia, Pagefactory si adatta solo agli elementi statici.
Q # 6) Esistono modi alternativi per identificare gli elementi sulla base di più criteri?
come aprire il file jar con java
Risposta: L'alternativa per identificare gli elementi in base a più criteri è utilizzare le annotazioni @FindAll e @FindBys. Queste annotazioni aiutano a identificare uno o più elementi a seconda dei valori recuperati dai criteri passati in esso.
# 1) @FindAll:
@FindAll può contenere più @FindBy e restituirà tutti gli elementi che corrispondono a @FindBy in un unico elenco. @FindAll viene utilizzato per contrassegnare un campo su un oggetto pagina per indicare che la ricerca deve utilizzare una serie di tag @FindBy. Quindi cercherà tutti gli elementi che corrispondono a uno dei criteri FindBy.
Si noti che non è garantito che gli elementi siano nell'ordine del documento.
La sintassi per utilizzare @FindAll è la seguente:
@FindAll( { @FindBy(how = How.ID, using = 'foo'), @FindBy(className = 'bar') } )
Spiegazione: @FindAll cercherà e identificherà elementi separati conformi a ciascuno dei criteri @FindBy e li elencherà. Nell'esempio precedente, cercherà prima un elemento il cui id = 'foo' e quindi identificherà il secondo elemento con className = 'bar'.
Supponendo che ci fosse un elemento identificato per ogni criterio FindBy, @FindAll risulterà nell'elencare 2 elementi, rispettivamente. Ricorda, potrebbero esserci più elementi identificati per ogni criterio. Quindi, in parole semplici, @ Trova tutto agisce equivalente al O operatore sui criteri @FindBy passati.
# 2) @FindBys:
FindBys viene utilizzato per contrassegnare un campo su un oggetto pagina per indicare che la ricerca deve utilizzare una serie di tag @FindBy in una catena come descritto in ByChained. Quando gli oggetti WebElement richiesti devono corrispondere a tutti i criteri forniti, utilizzare l'annotazione @FindBys.
La sintassi per utilizzare @FindBys è la seguente:
@FindBys( { @FindBy(name=”foo”) @FindBy(className = 'bar') } )
Spiegazione: @FindBys cercherà e identificherà gli elementi conformi a tutti i criteri di @FindBy e li elencherà. Nell'esempio precedente, cercherà elementi il cui nome = 'foo' e className = 'bar'.
@FindAll risulterà nell'elencare 1 elemento se assumiamo che ci fosse un elemento identificato con il nome e il className nei criteri dati.
Se non c'è un elemento che soddisfa tutte le condizioni di FindBy passate, la risultante di @FindBys sarà zero elementi. Potrebbe esserci un elenco di elementi web identificati se tutte le condizioni soddisfano più elementi. In parole semplici, @ FindBys agisce equivalente al E operatore sui criteri @FindBy passati.
Vediamo l'implementazione di tutte le annotazioni di cui sopra attraverso un programma dettagliato:
Modificheremo il programma www.nseindia.com fornito nella sezione precedente per comprendere l'implementazione delle annotazioni @FindBy, @FindBys e @FindAll
# 1) Il repository degli oggetti di PagefactoryClass viene aggiornato come di seguito:
List newlist = driver.findElements (By.tagName ('a'));
@FindBy (come = come. TAG_NAME , utilizzando = 'a')
privato Elenca findbyvalue;
@Trova tutto ({ @FindBy (className = 'sel'), @FindBy (xpath = '// a (@ id =’ tab5 ′) ')})
privato List findallvalue;
@FindBys ({ @FindBy (className = 'sel'), @FindBy (xpath = '// a (@ id =’ tab5 ′) ')})
privato List findbysvalue;
# 2) Un nuovo metodo seeHowFindWorks () è scritto nella PagefactoryClass e viene invocato come ultimo metodo nella classe Main.
Il metodo è il seguente:
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 Di seguito è riportato il risultato mostrato nella finestra della console dopo l'esecuzione del programma:

Proviamo ora a capire il codice in dettaglio:
# 1) Tramite il pattern design dell'oggetto pagina, l'elemento 'newlist' identifica tutti i tag con ancora 'a'. In altre parole, otteniamo un conteggio di tutti i collegamenti nella pagina.
Abbiamo appreso che pagefactory @FindBy fa lo stesso lavoro di driver.findElement (). L'elemento findbyvalue viene creato per ottenere il conteggio di tutti i link sulla pagina attraverso una strategia di ricerca avente un concetto pagefactory.
Si dimostra corretto che sia driver.findElement () che @FindBy fanno lo stesso lavoro e identificano gli stessi elementi. Se guardi lo screenshot della finestra della console risultante sopra, il conteggio dei collegamenti identificati con l'elemento newlist e quello di findbyvalue sono uguali, ad es. 299 link trovati nella pagina.
Il risultato è mostrato come di seguito:
driver.findElements(By.tagName()) 299 count of @FindBy- list elements 299
#Due) Qui approfondiamo il funzionamento dell'annotazione @FindAll che sarà di pertinenza della lista degli elementi web con il nome findallvalue.
Osservando attentamente ogni criterio @FindBy all'interno dell'annotazione @FindAll, il primo criterio @FindBy cerca elementi con className = 'sel' e il secondo criterio @FindBy cerca un elemento specifico con XPath = '// a (@ id = 'tab5')
Premiamo ora F12 per ispezionare gli elementi sulla pagina nseindia.com e ottenere alcuni chiarimenti sugli elementi corrispondenti ai criteri @FindBy.
Ci sono due elementi nella pagina corrispondenti a className = 'sel':
per) L'elemento 'Fundamentals' ha il tag list, ad es.
con className = 'sel'. Vedere l'istantanea di seguito

b) Un altro elemento 'Order Book' ha un XPath con un anchor tag che ha il nome della classe come 'sel'.

c) Il secondo @FindBy con XPath ha un anchor tag il cui id è ' tab5 '. C'è solo un elemento identificato in risposta alla ricerca che è Fondamentali.
Guarda l'istantanea qui sotto:

Quando è stato eseguito il test nseindia.com, abbiamo ottenuto il conteggio degli elementi cercati.
@FindAll as 3. Gli elementi per findallvalue quando visualizzati erano: Fondamentali come 0thelemento indice, Order Book come 1stelemento indice e Fondamentali di nuovo come 2ndelemento indice. Abbiamo già appreso che @FindAll identifica gli elementi per ogni criterio @FindBy separatamente.
Per lo stesso protocollo, per la ricerca del primo criterio, ovvero className = 'sel', ha identificato due elementi che soddisfano la condizione e ha recuperato 'Fundamentals' e 'Order Book'.
Quindi è passato al successivo criterio @FindBy e in base all'xpath fornito per il secondo @FindBy, potrebbe recuperare l'elemento 'Fundamentals'. Questo è il motivo per cui ha finalmente identificato 3 elementi, rispettivamente.
Pertanto, non ottiene gli elementi che soddisfano nessuna delle condizioni @FindBy ma tratta separatamente ciascuno dei @FindBy e identifica gli elementi allo stesso modo. Inoltre, nell'esempio corrente, abbiamo anche visto che non controlla se gli elementi sono unici ( Per esempio. L'elemento 'Fondamentali' in questo caso visualizzato due volte come parte del risultato dei due criteri @FindBy)
# 3) Qui approfondiamo il funzionamento dell'annotazione @FindBys che sarà pertinente alla lista degli elementi web con il nome findbysvalue. Anche qui, il primo criterio @FindBy cerca elementi con className = ’sel’ e il secondo criterio @FindBy cerca un elemento specifico con xpath = '// a (@ id =' tab5 ').
Ora che sappiamo, gli elementi identificati per la prima condizione @FindBy sono “Fundamentals” e “Order Book” e quello del secondo criterio @FindBy è “Fundamentals”.
Quindi, in che modo la risultante di @FindBys sarà diversa da @FindAll? Abbiamo appreso nella sezione precedente che @FindBys è equivalente all'operatore condizionale AND e quindi cerca un elemento o l'elenco di elementi che soddisfi tutte le condizioni @FindBy.
Secondo il nostro esempio attuale, il valore 'Fundamentals' è l'unico elemento che ha class = 'sel' e id = 'tab5', soddisfacendo entrambe le condizioni. Questo è il motivo per cui la dimensione di @FindBys in out testcase è 1 e mostra il valore come 'Fundamentals'.
Memorizzazione nella cache degli elementi in Pagefactory
Ogni volta che viene caricata una pagina, tutti gli elementi della pagina vengono nuovamente cercati invocando una chiamata tramite @FindBy o driver.findElement () e viene eseguita una nuova ricerca degli elementi nella pagina.
La maggior parte delle volte quando gli elementi sono dinamici o continuano a cambiare durante il runtime, specialmente se sono elementi AJAX, ha sicuramente senso che ad ogni caricamento della pagina ci sia una nuova ricerca di tutti gli elementi nella pagina.
Quando la pagina Web contiene elementi statici, la memorizzazione nella cache dell'elemento può essere utile in diversi modi. Quando gli elementi vengono memorizzati nella cache, non è necessario individuarli nuovamente durante il caricamento della pagina, ma può fare riferimento al repository degli elementi memorizzati nella cache. Ciò consente di risparmiare molto tempo ed aumenta le prestazioni migliori.
Pagefactory fornisce questa funzionalità di memorizzare nella cache gli elementi utilizzando un'annotazione @CacheLookUp .
L'annotazione dice al driver di utilizzare la stessa istanza del localizzatore dal DOM per gli elementi e di non cercarli di nuovo mentre il metodo initElements della pagefactory contribuisce in modo prominente alla memorizzazione dell'elemento statico memorizzato nella cache. Gli initElement eseguono il lavoro di memorizzazione nella cache degli elementi.
Ciò rende il concetto di pagefactory speciale rispetto al normale modello di progettazione degli oggetti di pagina. Ha i suoi pro e contro di cui parleremo un po 'più tardi. Ad esempio, il pulsante di accesso sulla home page di Facebook è un elemento statico, che può essere memorizzato nella cache ed è un elemento ideale da memorizzare nella cache.
Vediamo ora come implementare l'annotazione @CacheLookUp
Dovrai prima importare un pacchetto per Cachelookup come di seguito:
import org.openqa.selenium.support.CacheLookup
Di seguito è riportato lo snippet che mostra la definizione di un elemento utilizzando @CacheLookUp. Non appena UniqueElement viene cercato per la prima volta, initElement () memorizza la versione cache dell'elemento in modo che la volta successiva il driver non cerchi l'elemento invece si riferisca alla stessa cache ed esegua l'azione sull'elemento a destra lontano.
@FindBy(id = 'unique') @CacheLookup private WebElement UniqueElement;
Vediamo ora attraverso un programma reale come le azioni sull'elemento web memorizzato nella cache siano più veloci di quelle sull'elemento web non memorizzato nella cache:
Migliorando ulteriormente il programma nseindia.com ho scritto un altro nuovo metodo monitorPerformance () in cui creo un elemento memorizzato nella cache per la casella di ricerca e un elemento non memorizzato nella cache per la stessa casella di ricerca.
Quindi provo a ottenere il tagname dell'elemento 3000 volte sia per l'elemento memorizzato nella cache che per l'elemento non memorizzato nella cache e provo a misurare il tempo impiegato per completare l'attività sia dall'elemento memorizzato nella cache che da quello non memorizzato nella cache.
Ho considerato 3000 volte in modo da poter vedere una differenza visibile nei tempi per i due. Mi aspetto che l'elemento memorizzato nella cache completi l'acquisizione del nome tagname 3000 volte in minor tempo rispetto a quello dell'elemento non memorizzato nella cache.
Ora sappiamo perché l'elemento memorizzato nella cache dovrebbe funzionare più velocemente, ovvero il driver viene istruito a non cercare l'elemento dopo la prima ricerca ma continua a lavorarci direttamente e questo non è il caso dell'elemento non memorizzato nella cache per cui viene eseguita la ricerca dell'elemento tutte le 3000 volte e poi l'azione viene eseguita su di essa.
Di seguito è riportato il codice per il metodo 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'); }
All'esecuzione, vedremo il risultato seguente nella finestra della console:
In base al risultato, l'attività sull'elemento non memorizzato nella cache viene completata in 82 secondi mentre il tempo impiegato per completare l'attività sull'elemento memorizzato nella cache era solo 37 secondi. Questa è effettivamente una differenza visibile nel tempo di risposta di entrambi gli elementi memorizzati nella cache e non memorizzati nella cache.

D # 7) Quali sono i pro ei contro dell'annotazione @CacheLookUp nel concetto di Pagefactory?
Risposta:
Pro @CacheLookUp e situazioni fattibili per il suo utilizzo:
@CacheLookUp è fattibile quando gli elementi sono statici o non cambiano affatto durante il caricamento della pagina. Tali elementi non cambiano il tempo di esecuzione. In questi casi, è consigliabile utilizzare l'annotazione per migliorare la velocità complessiva dell'esecuzione del test.
Contro dell'annotazione @CacheLookUp:
Il più grande svantaggio di avere elementi memorizzati nella cache con l'annotazione è il timore di ottenere frequentemente StaleElementReferenceExceptions.
Gli elementi dinamici vengono aggiornati abbastanza spesso con quelli suscettibili di cambiare rapidamente in pochi secondi o minuti dell'intervallo di tempo.
Di seguito sono riportati alcuni esempi di tali elementi dinamici:
- Avere un cronometro sulla pagina web che mantiene il timer aggiornato ogni secondo.
- Una cornice che aggiorna costantemente il bollettino meteorologico.
- Una pagina che riporta gli aggiornamenti live di Sensex.
Questi non sono affatto ideali o fattibili per l'uso dell'annotazione @CacheLookUp. Se lo fai, corri il rischio di ottenere l'eccezione di StaleElementReferenceExceptions.
Memorizzando nella cache tali elementi, durante l'esecuzione del test, il DOM degli elementi viene modificato, tuttavia il driver cerca la versione del DOM che era già memorizzata durante la memorizzazione nella cache. Questo fa sì che l'elemento obsoleto venga cercato dal driver che non esiste più nella pagina web. Questo è il motivo per cui viene generata StaleElementReferenceException.
Classi di fabbrica:
Pagefactory è un concetto costruito su più classi e interfacce factory. Impareremo alcune classi e interfacce factory qui in questa sezione. Pochi dei quali vedremo lo sono AjaxElementLocatorFactory , ElementLocatorFactory e DefaultElementFactory.
Ci siamo mai chiesti se Pagefactory fornisce un modo per incorporare l'attesa implicita o esplicita per l'elemento fino a quando una certa condizione è soddisfatta ( Esempio: Fino a quando un elemento è visibile, abilitato, cliccabile, ecc.)? Se sì, ecco una risposta appropriata.
AjaxElementLocatorFactory è uno dei contributori significativi tra tutte le classi di fabbrica. Il vantaggio di AjaxElementLocatorFactory è che puoi assegnare un valore di timeout per un elemento web alla classe della pagina Oggetto.
Sebbene Pagefactory non fornisca una funzione di attesa esplicita, tuttavia, esiste una variante per l'attesa implicita utilizzando la classe AjaxElementLocatorFactory . Questa classe può essere utilizzata incorporata quando l'applicazione utilizza componenti ed elementi Ajax.
Ecco come implementarlo nel codice. All'interno del costruttore, quando usiamo il metodo initElements (), possiamo usare AjaxElementLocatorFactory per fornire un'attesa implicita sugli elementi.
PageFactory.initElements(driver, this); can be replaced with PageFactory.initElements( new AjaxElementLocatorFactory(driver, 20), this);
La seconda riga del codice sopra implica che il driver deve impostare un timeout di 20 secondi per tutti gli elementi sulla pagina quando ciascuno dei suoi carichi e se uno qualsiasi degli elementi non viene trovato dopo un'attesa di 20 secondi, viene lanciata 'NoSuchElementException' per quell'elemento mancante.
Puoi anche definire l'attesa come di seguito:
public pageFactoryClass(WebDriver driver) { ElementLocatorFactory locateMe = new AjaxElementLocatorFactory(driver, 30); PageFactory.initElements(locateMe, this); this.driver = driver; }
Il codice sopra funziona perfettamente perché la classe AjaxElementLocatorFactory implementa l'interfaccia ElementLocatorFactory.
Qui, l'interfaccia genitore (ElementLocatorFactory) fa riferimento all'oggetto della classe figlia (AjaxElementLocatorFactory). Quindi, il concetto Java di 'upcasting' o 'polimorfismo di runtime' viene utilizzato durante l'assegnazione di un timeout utilizzando AjaxElementLocatorFactory.
Rispetto a come funziona tecnicamente, AjaxElementLocatorFactory crea prima un AjaxElementLocator utilizzando un SlowLoadableComponent che potrebbe non aver terminato il caricamento quando ritorna load (). Dopo una chiamata a load (), il metodo isLoaded () dovrebbe continuare a fallire finché il componente non è stato completamente caricato.
In altre parole, tutti gli elementi verranno cercati di recente ogni volta che si accede a un elemento nel codice invocando una chiamata a locator.findElement () dalla classe AjaxElementLocator che quindi applica un timeout fino al caricamento tramite la classe SlowLoadableComponent.
Inoltre, dopo aver assegnato il timeout tramite AjaxElementLocatorFactory, gli elementi con l'annotazione @CacheLookUp non verranno più memorizzati nella cache poiché l'annotazione verrà ignorata.
C'è anche una variazione su come Puoi chiama il initElements () metodo e come tu non dovrebbe chiama il AjaxElementLocatorFactory per assegnare il timeout per un elemento.
# 1) Puoi anche specificare un nome di elemento invece dell'oggetto driver come mostrato di seguito nel metodo initElements ():
PageFactory.initElements( , this);
Il metodo initElements () nella variante precedente richiama internamente una chiamata alla classe DefaultElementFactory e il costruttore di DefaultElementFactory accetta l'oggetto dell'interfaccia SearchContext come parametro di input. L'oggetto driver Web e un elemento Web appartengono entrambi all'interfaccia SearchContext.
In questo caso, il metodo initElements () verrà inizializzato in anticipo solo sull'elemento menzionato e non tutti gli elementi sulla pagina web verranno inizializzati.
#Due) Tuttavia, ecco una svolta interessante a questo fatto che afferma come non dovresti chiamare l'oggetto AjaxElementLocatorFactory in un modo specifico. Se uso la variante sopra di initElements () insieme ad AjaxElementLocatorFactory, allora fallirà.
Esempio: Il codice seguente, ovvero il passaggio del nome dell'elemento anziché dell'oggetto driver alla definizione AjaxElementLocatorFactory non funzionerà poiché il costruttore per la classe AjaxElementLocatorFactory accetta solo l'oggetto driver Web come parametro di input e quindi l'oggetto SearchContext con l'elemento web non funzionerebbe per esso.
PageFactory.initElements(new AjaxElementLocatorFactory(, 10), this);
D # 8) L'uso di pagefactory è un'opzione fattibile rispetto al normale modello di progettazione degli oggetti della pagina?
Risposta: Questa è la domanda più importante che le persone hanno ed è per questo che ho pensato di affrontarla alla fine del tutorial. Ora conosciamo il 'dentro e fuori' di Pagefactory a partire dai suoi concetti, annotazioni utilizzate, funzionalità aggiuntive che supporta, implementazione tramite codice, pro e contro.
Tuttavia, rimaniamo con questa domanda essenziale che se pagefactory ha così tante cose buone, perché non dovremmo attenerci al suo utilizzo.
Pagefactory viene fornito con il concetto di CacheLookUp che abbiamo visto non è fattibile per elementi dinamici come i valori dell'elemento che vengono aggiornati spesso. Quindi, pagefactory senza CacheLookUp, è una buona opzione? Sì, se gli xpath sono statici.
Tuttavia, il rovescio della medaglia è che l'applicazione dell'era moderna è piena di elementi dinamici pesanti in cui sappiamo che il design dell'oggetto pagina senza pagefactory funziona alla fine bene, ma il concetto di pagefactory funziona altrettanto bene con xpath dinamici? Forse no. Ecco un rapido esempio:
Sulla pagina web nseindia.com, vediamo una tabella come mostrato di seguito.

L'xpath della tabella è
'//*(@id='tab9Content')/table/tbody/tr(+count+)/td(1)'
Vogliamo recuperare i valori da ogni riga per la prima colonna 'Acquista Qtà'. Per fare questo dovremo incrementare il contatore delle righe ma l'indice della colonna rimarrà 1. Non c'è modo che possiamo passare questo XPath dinamico nell'annotazione @FindBy poiché l'annotazione accetta valori che sono statici e nessuna variabile può essere trasmessa esso.
Qui è dove il pagefactory fallisce completamente mentre il solito POM funziona alla grande con esso. È possibile utilizzare facilmente un ciclo for per incrementare l'indice di riga utilizzando tali xpath dinamici nel metodo driver.findElement ().
Conclusione
Page Object Model è un concetto o modello di design utilizzato nel framework di automazione Selenium.
La denominazione della convezione dei metodi è intuitiva nel modello a oggetti di pagina. Il codice in POM è facile da capire, riutilizzabile e gestibile. In POM, se c'è qualche cambiamento nell'elemento web, è sufficiente apportare le modifiche nella rispettiva classe, piuttosto che modificare tutte le classi.
Pagefactory, proprio come il solito POM, è un concetto meraviglioso da applicare. Tuttavia, dobbiamo sapere dove è fattibile il solito POM e dove si adatta bene Pagefactory. Nelle applicazioni statiche (dove sia XPath che gli elementi sono statici), Pagefactory può essere liberamente implementato con ulteriori vantaggi di prestazioni migliori.
In alternativa, quando l'applicazione coinvolge elementi sia dinamici che statici, potresti avere un'implementazione mista del pom con Pagefactory e quella senza Pagefactory secondo la fattibilità per ogni elemento web.
Autore: questo tutorial è stato scritto da Shobha D. Lavora come Project Lead e vanta oltre 9 anni di esperienza in manuale, automazione (Selenium, IBM Rational Functional Tester, Java) e API Testing (SOAPUI e Rest assicurato in Java) .
Ora passiamo a te, per l'ulteriore implementazione di Pagefactory.
Buona esplorazione !!!
=> Visita qui per imparare il selenio da zero.
Lettura consigliata
- 30+ Migliori tutorial sul selenio: impara il selenio con esempi reali
- Scripting efficiente del selenio e scenari di risoluzione dei problemi - Tutorial sul selenio n. 27
- Debug degli script di selenio con i registri (tutorial di Log4j) - Esercitazione di selenio # 26
- Introduzione a JUnit Framework e al suo utilizzo in Selenium Script - Selenium Tutorial # 11
- 7 fattori che influenzano la stima del test del progetto Selenium Automation - Selenium Tutorial # 32
- Asserzioni in selenio utilizzando framework Junit e TestNG
- Come utilizzare TestNG Framework per la creazione di script di selenio - TestNG Selenium Tutorial # 12
- Scopri come utilizzare le annotazioni TestNG in selenio (con esempi)