page object model with page factory selenium tutorial
Denna djupgående handledning förklarar allt om sidobjektmodell (POM) med sidfabrik med hjälp av exempel. Du kan också lära dig implementeringen av POM i selen:
I denna handledning kommer vi att förstå hur man skapar en Page Object Model med hjälp av Page Factory-metoden. Vi kommer att fokusera på:
- Fabriksklass
- Hur man skapar en grundläggande POM med hjälp av Page Factory Pattern
- Olika anteckningar som används i sidfabriksinriktningen
Innan vi ser vad som är Pagefactory och hur det kan användas tillsammans med Page-objektmodellen, låt oss förstå vad som är Page Object Model som är allmänt känt som POM.
=> Besök här för att se Selenium Training Series for All.
Vad du kommer att lära dig:
- Vad är Page Object Model (POM)?
- Vad är Pagefactory?
- POM använder Page Factory
- Vanliga frågor
- Slutsats
Vad är Page Object Model (POM)?
Teoretiska terminologier beskriver Sidobjektmodell som ett designmönster som används för att bygga ett objektförvar för de webbelement som är tillgängliga i applikationen som testas. Få andra hänvisar till det som ett ramverk för Selen-automatisering för den givna applikationen som testas.
Men vad jag har förstått om termen Page Object Model är:
# 1) Det är ett designmönster där du har en separat Java-klassfil som motsvarar varje skärm eller sida i applikationen. Klassfilen kan inkludera objektförvaret för UI-elementen samt metoder.
#två) Om det finns enorma webbelement på en sida, kan objektförrådsklassen för en sida separeras från klassen som innehåller metoder för motsvarande sida.
Exempel: Om sidan Registrera konto har många inmatningsfält kan det finnas en klass RegisterAccountObjects.java som bildar objektförvaret för UI-elementen på sidan för registerkonton.
En separat klassfil RegisterAccount.java som utökar eller ärver RegisterAccountObjects som innehåller alla metoder som utför olika åtgärder på sidan kan skapas.
# 3) Dessutom kan det finnas ett generiskt paket med en {roperties-fil, Excel-testdata och vanliga metoder under ett paket.
Exempel: DriverFactory som kan användas mycket enkelt på alla sidor i applikationen
Förstå POM med exempel
Kolla upp här för att lära dig mer om POM.
Nedan följer en ögonblicksbild av webbsidan:
Genom att klicka på var och en av dessa länkar omdirigeras användaren till en ny sida.
Här är ögonblicksbilden av hur projektstrukturen med Selen är byggd med hjälp av den sidobjektmodell som motsvarar varje sida på webbplatsen. Varje Java-klass innehåller objektförvar och metoder för att utföra olika åtgärder på sidan.
Dessutom kommer det att finnas en annan JUNIT eller TestNG eller en Java-klassfil som anropar samtal till klassfiler på dessa sidor.
Varför använder vi sidobjektmodellen?
Användningen av detta kraftfulla Selen-ram kallas POM eller sidobjektmodell. Nu uppstår frågan som “Varför använda POM?”.
Det enkla svaret på detta är att POM är en kombination av datadrivna, modulära och hybridramar. Det är ett tillvägagångssätt för att systematiskt organisera skript på ett sådant sätt att det gör det enkelt för QA att behålla koden utan krångel och också hjälper till att förhindra överflödig eller duplicerad kod.
Till exempel, om det finns en förändring i lokaliseringsvärdet på en viss sida, är det väldigt enkelt att identifiera och göra den snabba ändringen endast i skriptet på respektive sida utan att påverka koden någon annanstans.
Vi använder konceptet Page Object Model i Selenium Webdriver av följande skäl:
- Ett objektförvar skapas i denna POM-modell. Det är oberoende av testfall och kan återanvändas för ett annat projekt.
- Namngivningskonventionen för metoder är mycket enkel, förståelig och mer realistisk.
- Under sidobjektmodellen skapar vi sidklasser som kan återanvändas i ett annat projekt.
- Sidobjektmodellen är lätt för det utvecklade ramverket på grund av dess flera fördelar.
- I den här modellen skapas separata klasser för olika sidor i en webbapplikation som inloggningssida, hemsidan, anställds detaljeringssida, byta lösenordssida etc.
- Om det finns någon förändring i något element på en webbplats behöver vi bara göra ändringar i en klass och inte i alla klasser.
- Det manus som designats är mer återanvändbart, läsbart och underhållbart i sidobjektmodellmetoden.
- Projektstrukturen är ganska enkel och förståelig.
- Kan använda PageFactory i sidobjektmodellen för att initialisera webbelementet och lagra element i cachen.
- TestNG kan också integreras i metoden Page Object Model.
Implementering av enkel POM i selen
# 1) Scenario att automatisera
Nu automatiserar vi det givna scenariot med hjälp av Page Object Model.
Scenariot förklaras nedan:
Steg 1: Starta webbplatsen “https: //demo.vtiger.com”.
Steg 2: Ange giltig referens.
Steg 3: Logga in på webbplatsen.
Steg 4: Verifiera startsidan.
Steg 5: Logga ut webbplatsen.
Steg 6: Stäng webbläsaren.
# 2) Selen-skript för ovanstående scenario i POM
Nu skapar vi POM-strukturen i Eclipse, som förklaras nedan:
Steg 1: Skapa ett projekt i Eclipse - POM-baserad struktur:
a) Skapa projekt ”Sidobjektmodell”.
b) Skapa 3-paket under projektet.
- bibliotek
- sidor
- testfall
Bibliotek: Under detta sätter vi de koder som behöver anropas om och om igen i våra testfall som webbläsarstart, skärmdumpar etc. Användaren kan lägga till fler klasser under det baserat på projektbehovet.
Sidor: Under detta skapas klasser för varje sida i webbapplikationen och kan lägga till fler sidklasser baserat på antalet sidor i applikationen.
Testfall: Under detta skriver vi inloggningstestfallet och kan lägga till fler testfall efter behov för att testa hela applikationen.
c) Klasser under paketen visas i bilden nedan.
Steg två: Skapa följande klasser under bibliotekspaketet.
Webbläsare.java: I denna klass definieras tre webbläsare (Firefox, Chrome och Internet Explorer) och det kallas i inloggningstestfallet. Baserat på kravet kan användaren också testa applikationen i olika webbläsare.
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: I den här klassen skrivs ett skärmdumpsprogram och det anropas i testfallet när användaren vill ta en skärmdump om testet misslyckas eller godkänns.
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(); } } }
Steg 3 : Skapa sidklasser under Sidpaket.
Hemsida.java: Det här är hemsidaklassen, där alla element på hemsidan och metoder definieras.
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: Detta är inloggningssideklassen, där alla element på inloggningssidan och metoder definieras.
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(); } }
Steg 4: Skapa testfall för inloggningsscenariot.
LoginTestCase.java: Detta är klassen LoginTestCase, där testfallet utförs. Användaren kan också skapa fler testfall enligt projektbehovet.
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(); } }
Steg 5: Kör “LoginTestCase.java”.
Steg 6: Resultat av sidobjektmodellen:
- Starta Chrome-webbläsaren.
- Demosidan öppnas i webbläsaren.
- Logga in på demosidan.
- Verifiera hemsidan.
- Logga ut webbplatsen.
- Stäng webbläsaren.
Låt oss nu utforska det främsta konceptet i den här handledningen som fångar uppmärksamheten, dvs. “Pagefactory”.
Vad är Pagefactory?
PageFactory är ett sätt att implementera ”Page Object Model”. Här följer vi principen om separation av Page Object Repository och Test Methods. Det är ett inbyggt koncept för Page Object Model som är mycket optimerat.
Låt oss nu få mer tydlighet om termen Pagefactory.
# 1) För det första ger konceptet Pagefactory ett alternativt sätt när det gäller syntax och semantik för att skapa ett objektförvar för webbelementen på en sida.
#två) För det andra använder den en något annorlunda strategi för initialisering av webbelementen.
# 3) Objektförvaret för UI-webbelementen kan byggas med:
- Vanlig ”POM utan Pagefactory” och,
- Alternativt kan du använda ”POM med Pagefactory”.
Nedan följer en bildrepresentation av samma:
Nu ska vi titta på alla aspekter som skiljer den vanliga POM från POM med Pagefactory.
a) Skillnaden i syntaxen för att lokalisera ett element med vanlig POM vs POM med Pagefactory.
Till exempel , Klick här för att hitta sökfältet som visas på sidan.
POM utan sidfabrik:
# 1) Nedan följer hur du hittar sökfältet med den vanliga POM:
WebElement searchNSETxt=driver.findElement(By.id(“searchBox”));
# 2) Nedanstående steg överför värdet 'investering' till Sök NSE-fältet.
searchNSETxt.sendkeys(“investment”);
POM använder Pagefactory:
# 1) Du kan hitta sökfältet med Pagefactory enligt nedan.
Anteckningen @FindBy används i Pagefactory för att identifiera ett element medan POM utan Pagefactory använder driver.findElement () metod för att lokalisera ett element.
Det andra uttalandet för Pagefactory efter @FindBy tilldelar en typ WebElement klass som fungerar precis som tilldelningen av ett elementnamn av typen WebElement-klass som en returtyp av metoden driver.findElement () som används i vanliga POM (searchNSETxt i detta exempel).
Vi kommer att titta på @FindBy anteckningar i detalj i den kommande delen av denna handledning.
@FindBy(id = 'searchBox') WebElement searchNSETxt;
#två) Nedanstående steg överför värdet 'investering' till Sök NSE-fältet och syntaxen förblir densamma som för den vanliga POM (POM utan Pagefactory).
searchNSETxt.sendkeys(“investment”);
b) Skillnaden i strategin för initialisering av webbelement med vanlig POM vs POM med Pagefactory.
Använda POM utan sidfaktor:
Nedan finns ett kodavsnitt för att ställa in Chrome-drivrutinssökvägen. En WebDriver-instans skapas med namndrivrutinen och ChromeDriver tilldelas 'drivrutinen'. Samma förarobjekt används sedan för att starta National Stock Exchange-webbplatsen, lokalisera sökrutan och ange strängvärdet i fältet.
Poängen som jag vill markera här är att när det är POM utan sidfabrik skapas drivrutinsinstansen initialt och varje webbelement initialiseras nyligen varje gång det ringer till det webbelementet med driver.findElement () eller driver .findElements ().
Det är därför, med ett nytt steg av driver.findElement () för ett element, skannas DOM-strukturen igen igen och uppdateras identifieringen av elementet på den sidan.
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”);
Använda POM med Pagefactory:
Förutom att använda @FindBy-annotering istället för metoden driver.findElement (), används även kodavsnittet nedan för Pagefactory. Den statiska initElements () -metoden i PageFactory-klassen används för att initialisera alla UI-element på sidan så snart sidan laddas.
public PagefactoryClass(WebDriver driver) { this.driver = driver; PageFactory.initElements(driver, this); }
Ovanstående strategi gör PageFactory-metoden något annorlunda än den vanliga POM. I den vanliga POM måste webbelementet initialiseras uttryckligen medan i Pagefactory-metoden initialiseras alla element med initElements () utan att varje webbelement uttryckligen initialiseras.
Till exempel: Om WebElement deklarerades men inte initialiserades i den vanliga POM-filen, kastas 'initialiseringsvariabel' -fel eller NullPointerException. Därför måste i varje vanlig POM initialiseras varje WebElement. PageFactory kommer med en fördel jämfört med den vanliga POM i detta fall.
Låt oss inte initialisera webbelementet BDate (POM utan Pagefactory) kan du se att felet 'Initiera variabel' visas och uppmanar användaren att initialisera den till noll, så du kan inte anta att elementen initialiseras implicit när de lokaliseras.
Element BDate initialiserades uttryckligen (POM utan Pagefactory):
Låt oss nu titta på ett par instanser av ett komplett program med PageFactory för att utesluta tvetydighet när det gäller att förstå implementeringsaspekten.
Exempel 1:
- Gå till 'http://www.nseindia.com/'
- Välj 'Valutaderivat' i rullgardinsmenyn bredvid sökfältet.
- Sök efter 'USDINR'. Verifiera texten ”US Dollar-Indian Rupee - USDINR” på den resulterande sidan.
Programstruktur:
- PagefactoryClass.java som innehåller ett objektförvar med hjälp av sidan fabrikskoncept för nseindia.com som är en konstruktör för att initiera alla webbelement skapas, metod selectCurrentDerivative () för att välja värde från rullgardinsfältet Sökruta, välj Symbol () för att välja en symbol på sida som visas nästa och verifierar text () för att verifiera om sidhuvudet är som förväntat eller inte.
- NSE_MainClass.java är huvudklassfilen som anropar alla ovanstående metoder och utför respektive åtgärder på NSE-webbplatsen.
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 Exempel 2:
- Gå till 'https://www.shoppersstop.com/brands'
- Navigera till Haute curry-länken.
- Kontrollera om Haute Curry-sidan innehåller texten ”Starta nytt någonting”.
Programstruktur
- shopperstopPagefactory.java som innehåller ett objektförvar med hjälp av pagefactory-konceptet för shoppersstop.com som är en konstruktör för att initialisera alla webbelement skapas, metoder closeExtraPopup () för att hantera en popup-ruta för varning som öppnas, klicka på OnHauteCurryLink () för att klicka på Haute Curry Länka och verifieraStartNewSomething () för att verifiera om Haute Curry-sidan innehåller texten ”Starta nytt”.
- Shopperstop_CallPagefactory.java är huvudklassfilen som anropar alla ovanstående metoder och utför respektive åtgärder på NSE-webbplatsen.
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 använder Page Factory
Videohandledning - POM med sidfabrik
Del I
Del II
En fabriksklass används för att göra användning av sidobjekt enklare och enklare.
- Först måste vi hitta webbelementen genom anteckningar @FindBy i sidklasser .
- Initiera sedan elementen med initElements () när sidklassen initieras.
# 1) @FindBy:
@FindBy-anteckningen används i PageFactory för att lokalisera och deklarera webbelementen med hjälp av olika lokaliserare.Här skickar vi attributet såväl som dess värde som används för att lokalisera webbelementet till @FindBy-anteckningen och sedan deklareras WebElement.
Det finns två sätt på vilka anteckningen kan användas.
Till exempel:
@FindBy(how = How.ID, using='EmailAddress') WebElement Email; @FindBy(id='EmailAddress') WebElement Email;
Det förstnämnda är dock det vanliga sättet att deklarera WebElements.
'Hur' är en klass och den har statiska variabler som ID, XPATH, CLASSNAME, LINKTEXT, etc.
'använder sig av' - Att tilldela ett värde till en statisk variabel.
I ovanstående exempel , har vi använt attributet 'id' för att hitta webbelementet 'E-post'. På samma sätt kan vi använda följande sökare med @FindBy-anteckningarna:
- klassnamn
- css
- namn
- xpath
- taggnamn
- linkText
- partialLinkText
# 2) initElements ():
InitElements är en statisk metod av PageFactory-klass som används för att initialisera alla webbelement som lokaliseras av @FindBy-anteckningen. Således kan du enkelt starta sidklasserna.
initElements(WebDriver driver, java.lang.Class pageObjectClass)
Vi bör också förstå att POM följer OOPS-principer.
- WebElements deklareras som privata medlemsvariabler (Data Hiding).
- Bindande WebElements med motsvarande metoder (Encapsulation).
Steg för att skapa POM med hjälp av Page Factory Pattern
# 1) Skapa en separat Java-klassfil för varje webbsida.
#två) I varje klass ska alla WebElements deklareras som variabler (med kommentar - @FindBy) och initialiseras med metoden initElement (). WebElements deklarerade måste initieras för att användas i åtgärdsmetoderna.
# 3) Definiera motsvarande metoder som verkar på dessa variabler.
Låt oss ta ett exempel på ett enkelt scenario:
- Öppna webbadressen till en applikation.
- Skriv e-postadress och lösenordsdata.
- Klicka på inloggningsknappen.
- Verifiera lyckat inloggningsmeddelande på söksidan.
Sidlager
Här har vi två sidor,
- Hemsida - Sidan som öppnas när URL: n anges och där vi anger data för inloggning.
- Sök sida - En sida som visas efter en lyckad inloggning.
I sidlagret förklaras varje sida i webbapplikationen som en separat Java-klass och dess lokaliserare och åtgärder nämns där.
Steg för att skapa POM med realtidsexempel
# 1) Skapa en Java-klass för varje sida:
I denna exempel , kommer vi åt två webbsidor, 'Hem' och 'Sök' -sidor.
Därför skapar vi två Java-klasser i Page Layer (eller i ett paket säg com.automation.pages).
Package Name :com.automation.pages HomePage.java SearchPage.java
# 2) Definiera WebElements som variabler med hjälp av Annotation @FindBy:
Vi skulle interagera med:
- E-post, lösenord, inloggningsknappfält på startsidan.
- Framgångsrikt meddelande på söksidan.
Så vi kommer att definiera WebElements med @FindBy
Till exempel: Om vi ska identifiera EmailAddress med attribut-id är dess variabla deklaration
//Locator for EmailId field @FindBy(how=How.ID,using='EmailId') private WebElementEmailIdAddress;
# 3) Skapa metoder för åtgärder som utförs på WebElements.
Nedanstående åtgärder utförs på WebElements:
- Skriv åtgärd i fältet E-postadress.
- Skriv åtgärd i fältet Lösenord.
- Klicka på åtgärden på inloggningsknappen.
Till exempel, Användardefinierade metoder skapas för varje åtgärd på WebElement som,
public void typeEmailId(String Id){ driver.findElement(EmailAddress).sendKeys(Id) }
Här skickas Id som en parameter i metoden, eftersom input kommer att skickas av användaren från huvudtestfallet.
Notera :En konstruktör måste skapas i var och en av klasserna i sidlagret för att få drivrutinsinstansen från huvudklassen i testlagret och också för att initialisera WebElements (sidobjekt) som deklarerats i sidklassen med hjälp av PageFactory.InitElement () .
Vi initierar inte drivrutinen här, utan dess instans tas emot från huvudklassen när objektet för Page Layer-klassen skapas.
InitElement () - används för att initialisera deklarerade WebElements, med drivrutinsinstans från huvudklassen. Med andra ord skapas WebElements med hjälp av drivrutinsinstansen. Först efter att WebElements har initierats kan de användas i metoderna för att utföra åtgärder.
Två Java-klasser skapas för varje sida enligt nedan:
Hemsida.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. } }
Testa lager
Testfall implementeras i denna klass. Vi skapar ett separat paket säger, com.automation.test och skapar sedan en Java-klass här (MainClass.java)
Steg för att skapa testfall:
- Initiera drivrutinen och öppna programmet.
- Skapa ett objekt från PageLayer-klassen (för varje webbsida) och skicka drivrutinsinstansen som en parameter.
- Använd det skapade objektet och ring till metoderna i PageLayer-klassen (för varje webbsida) för att utföra åtgärder / verifiering.
- Upprepa steg 3 tills alla åtgärder utförs och stäng sedan drivrutinen.
//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(); } }
Annarkeringstyphierarki som används för att deklarera WebElements
Kommentarer används för att skapa en platsstrategi för gränssnittselementen.
# 1) @FindBy
När det gäller Pagefactory fungerar @FindBy som en magisk trollstav. Det tillför all kraft till konceptet. Du är nu medveten om att @FindBy-anteckningen i Pagefactory utför samma som driver.findElement () i den vanliga sidobjektmodellen. Den används för att lokalisera WebElement / WebElements med ett kriterium .
# 2) @FindBys
Den används för att hitta WebElement med mer än ett kriterium och måste matcha alla givna kriterier. Dessa kriterier bör nämnas i ett förhållande mellan förälder och barn. Med andra ord använder detta OCH villkorligt förhållande för att lokalisera WebElements med de angivna kriterierna. Den använder flera @ FindBy för att definiera varje kriterium.
Till exempel:
HTML-källkod för ett WebElement:
I POM:
@FindBys({ @FindBy(id = 'searchId_1'), @FindBy(name = 'search_field') }) WebElementSearchButton;
I exemplet ovan finns WebElement 'SearchButton' endast om det matchar båda kriterierna vars id-värde är 'searchId_1' och namnvärdet är 'search_field'. Observera att de första kriterierna tillhör en överordnad tagg och det andra kriteriet för en underordnad tagg.
# 3) @FindAll
Den används för att hitta WebElement med mer än ett kriterium och det måste matcha minst ett av de angivna kriterierna. Detta använder ELLER villkorliga relationer för att lokalisera WebElements. Den använder flera @ FindBy för att definiera alla kriterier.
Till exempel:
HTML källkod:
I POM:
@FindBys({ @FindBy(id = 'UsernameNameField_1'), // doesn’t match @FindBy(name = 'User_Id') //matches @FindBy(className = “UserName_r”) //matches }) WebElementUserName;
I ovanstående exempel finns WebElement-användarnamnet om det matchar minst en av de nämnda kriterierna.
# 4) @CacheLookUp
När WebElement oftare används i testfall letar Selen upp för WebElement varje gång testskriptet körs. I de fall där vissa WebElements används globalt för alla TC ( Till exempel, Inloggningsscenario inträffar för varje TC), den här anteckningen kan användas för att behålla dessa WebElements i cacheminnet när det läses för första gången.
Detta i sin tur hjälper koden att köras snabbare eftersom varje gång den inte behöver söka efter WebElement på sidan, snarare kan den få sin referens från minnet.
Detta kan vara som ett prefix med någon av @FindBy, @FindBys och @FindAll.
Till exempel:
@CacheLookUp @FindBys({ @FindBy(id = 'UsernameNameField_1'), @FindBy(name = 'User_Id') @FindBy(className = “UserName_r”) }) WebElementUserName;
Observera också att denna kommentar endast ska användas till WebElements vars attributvärde (som xpath, id-namn, klassnamn etc.) inte ändras ganska ofta. När WebElement har hittats för första gången behåller den sin referens i cacheminnet.
Så det händer en förändring av WebElement-attributet efter några dagar, Selenium kommer inte att kunna hitta elementet, eftersom det redan har sin gamla referens i sitt cacheminne och inte kommer att beakta den senaste ändringen i WebElement.
Mer på PageFactory.initElements ()
Nu när vi förstår strategin för Pagefactory för att initialisera webbelementen med InitElements (), ska vi försöka förstå de olika versionerna av metoden.
Metoden som vi vet tar drivarobjektet och det aktuella klassobjektet som ingångsparametrar och returnerar sidobjektet genom att implicit och proaktivt initiera alla element på sidan.
I praktiken är användningen av konstruktorn som visas i avsnittet ovan att föredra framför andra sätt för dess användning.
Alternativa sätt att ringa metoden är:
# 1) Istället för att använda 'den här' pekaren kan du skapa det aktuella klassobjektet, skicka drivrutinsinstansen till det och anropa den statiska metoden initElements med parametrar, dvs driverobjektet och klassobjektet som just skapades.
public PagefactoryClass(WebDriver driver) { //version 2 PagefactoryClass page=new PagefactoryClass(driver); PageFactory.initElements(driver, page); }
#två) Det tredje sättet att initiera element med Pagefactory-klassen är att använda api som kallas ”reflektion”. Ja, istället för att skapa ett klassobjekt med ett 'nytt' nyckelord kan klassnamn.klass skickas som en del av inmatningsparametern initElements ().
public PagefactoryClass(WebDriver driver) { //version 3 PagefactoryClass page=PageFactory.initElements(driver, PagefactoryClass.class); }
Vanliga frågor
F # 1) Vilka är de olika lokaliseringsstrategierna som används för @FindBy?
Svar: Det enkla svaret på detta är att det inte finns några olika lokaliseringsstrategier som används för @FindBy.
De använder samma åtta lokaliseringsstrategier som findElement () -metoden i vanliga POM använder:
- id
- namn
- klassnamn
- xpath
- css
- taggnamn
- linkText
- partialLinkText
F # 2) Finns det olika versioner av användningen av @FindBy-anteckningar också?
Svar: När det finns ett webbelement som ska sökas använder vi kommentaren @FindBy. Vi kommer att utarbeta alternativa sätt att använda @FindBy tillsammans med de olika lokaliseringsstrategierna.
Vi har redan sett hur man använder version 1 av @FindBy:
@FindBy(id = 'cidkeyword') WebElement Symbol;
Version 2 av @FindBy är genom att skicka inmatningsparametern som På vilket sätt och Använder sig av .
På vilket sätt letar efter lokaliseringsstrategin med vilken webbelementet skulle identifieras. Nyckelordet använder sig av definierar lokaliseringsvärdet.
Se nedan för bättre förståelse,
- How.ID söker i elementet med id strategi och det element som den försöker identifiera har id = cidkeyword.
@FindBy(how = How.ID, using = ' cidkeyword') WebElement Symbol;
- How.CLASS_NAME söker i elementet med klassnamn strategi och det element som den försöker identifiera har klass = ny klass.
@FindBy(how = How.CLASS_NAME, using = 'newclass') WebElement Symbol;
F # 3) Finns det någon skillnad mellan de två versionerna av @FindBy?
Svar: Svaret är Nej, det finns ingen skillnad mellan de två versionerna. Det är bara att den första versionen är den kortare och enklare jämfört med den andra versionen.
F # 4) Vad använder jag i sidfabriken om det finns en lista med webbelement?
Svar: I det vanliga designmönstret för sidobjekt har vi driver.findElements () för att hitta flera element som tillhör samma klass eller taggnamn, men hur hittar vi sådana element i fallet med sidobjektmodellen med Pagefactory? Det enklaste sättet att uppnå sådana element är att använda samma kommentar @FindBy.
Jag förstår att denna linje verkar vara en huvudskrapa för många av er. Men ja, det är svaret på frågan.
Låt oss titta på exemplet nedan:
Med den vanliga sidobjektmodellen utan Pagefactory använder du driver.findElements för att hitta flera element som visas nedan:
private List multipleelements_driver_findelements = driver.findElements (By.class(“last”));
Samma kan uppnås med hjälp av sidobjektmodellen med Pagefactory enligt nedan:
@FindBy (how = How.CLASS_NAME, using = 'last') private List multipleelements_FindBy;
I grund och botten gör tilldelningen av elementen till en lista av typen WebElement tricket oavsett om Pagefactory har använts eller inte när elementen identifieras och lokaliseras.
F # 5) Kan både design av sidobjekt utan sidfabrik och med Pagefactory användas i samma program?
Svar: Ja, både sidobjektdesign utan Pagefactory och med Pagefactory kan användas i samma program. Du kan gå igenom programmet nedan Svar på fråga nr 6 för att se hur båda används i programmet.
En sak att komma ihåg är att Pagefactory-konceptet med den cachade funktionen bör undvikas på dynamiska element medan sidobjektdesign fungerar bra för dynamiska element. Pagefactory passar dock bara statiska element.
F # 6) Finns det alternativa sätt att identifiera element baserat på flera kriterier?
bästa pc-rengörings- och optimeringsfri
Svar: Alternativet för att identifiera element baserat på flera kriterier är att använda kommentarerna @FindAll och @FindBys. Dessa anteckningar hjälper till att identifiera enskilda eller flera element beroende på de värden som hämtats från de kriterier som skickas i den.
# 1) @FindAll:
@FindAll kan innehålla flera @FindBy och returnerar alla element som matchar alla @FindBy i en enda lista. @FindAll används för att markera ett fält på ett sidobjekt för att indikera att sökningen ska använda en serie @FindBy-taggar. Den söker sedan efter alla element som matchar något av FindBy-kriterierna.
Observera att elementen inte garanteras att vara i dokumentordning.
Syntaksen för att använda @FindAll är enligt nedan:
@FindAll( { @FindBy(how = How.ID, using = 'foo'), @FindBy(className = 'bar') } )
Förklaring: @FindAll söker och identifierar separata element som uppfyller vart och ett av @FindBy-kriterierna och listar dem. I exemplet ovan kommer det först att söka i ett element vars id = ”foo” och sedan identifiera det andra elementet med className = ”bar”.
Förutsatt att det identifierades ett element för varje FindBy-kriterium kommer @FindAll att leda till att två element listas ut. Kom ihåg att det kan finnas flera element som identifierats för varje kriterium. Således, med enkla ord, @ Hitta alla fungerar likvärdigt med ELLER operatör på @FindBy-kriterierna godkända.
# 2) @FindBys:
FindBys används för att markera ett fält på ett sidobjekt för att indikera att uppslag ska använda en serie @FindBy-taggar i en kedja som beskrivs i ByChained. När de nödvändiga WebElement-objekten måste matcha alla givna kriterier använder du @FindBys-kommentar.
Syntaksen för att använda @FindBys är enligt nedan:
@FindBys( { @FindBy(name=”foo”) @FindBy(className = 'bar') } )
Förklaring: @FindBys söker och identifierar element som uppfyller alla @FindBy-kriterierna och listar dem. I exemplet ovan kommer det att söka i element vars namn = ”foo” och className = ”bar”.
@FindAll resulterar i att ett element listas ut om vi antar att det fanns ett element som identifierades med namnet och className i de angivna kriterierna.
Om det inte finns ett element som uppfyller alla godkända FindBy-villkor kommer resultatet av @FindBys att vara noll element. Det kan finnas en lista över webbelement som identifierats om alla villkor uppfyller flera element. Med enkla ord, @ FindBys fungerar likvärdigt med OCH operatör på @FindBy-kriterierna godkända.
Låt oss se implementeringen av alla ovanstående kommentarer genom ett detaljerat program:
Vi kommer att modifiera www.nseindia.com-programmet i föregående avsnitt för att förstå implementeringen av kommentarerna @FindBy, @FindBys och @FindAll
# 1) Objektförvaret för PagefactoryClass uppdateras enligt nedan:
Lista newlist = driver.findElements (By.tagName (“a”));
@FindBy (hur = hur. TAGGNAMN , med = “a”)
privat Lista findbyvalue;
@Hitta alla ({ @FindBy (className = “sel”), @FindBy (xpath = ”// a (@ id =’ tab5 ′) ”)})
privat Lista findallvalue;
@FindBys ({ @FindBy (className = “sel”), @FindBy (xpath = ”// a (@ id =’ tab5 ′) ”)})
privat Lista findbysvalue;
# 2) En ny metod seeHowFindWorks () skrivs i PagefactoryClass och åberopas som den sista metoden i huvudklassen.
Metoden är som nedan:
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 Nedan visas resultatet som visas i konsolfönstret efter genomförandet av programmet:

Låt oss nu försöka förstå koden i detalj:
# 1) Genom sidmönsterets designmönster identifierar elementet 'newlist' alla taggar med ankare 'a'. Med andra ord får vi ett antal av alla länkar på sidan.
Vi fick reda på att sidfabriken @FindBy gör samma jobb som driver.findElement (). Elementet findbyvalue skapas för att få antalet länkar på sidan genom en sökstrategi med ett sidfabriksbegrepp.
Det visar sig vara korrekt att både driver.findElement () och @FindBy gör samma jobb och identifierar samma element. Om du tittar på skärmdumpen av det resulterande konsolfönstret ovan är antalet länkar som identifieras med elementet newlist och det för findbyvalue lika, dvs. 299 länkar som finns på sidan.
Resultatet visades enligt nedan:
driver.findElements(By.tagName()) 299 count of @FindBy- list elements 299
#två) Här utarbetar vi arbetet med @FindAll-anteckningen som kommer att hänföras till listan över webbelement med namnet findallvalue.
Titta noga på varje @FindBy-kriterium i @FindAll-anteckningen, det första @FindBy-kriteriet söker efter element med className = 'sel' och det andra @FindBy-kriteriet söker efter ett specifikt element med XPath = “// a (@ id = 'tab5')
Låt oss nu trycka på F12 för att inspektera elementen på sidan nseindia.com och få vissa klarheter om element som motsvarar @FindBy-kriterierna.
Det finns två element på sidan som motsvarar className = ”sel”:
till) Elementet 'Fundamentals' har listtaggen, dvs.
med className = ”sel”. Se ögonblicksbild nedan

b) Ett annat element 'Order Book' har en XPath med en ankartagg som har klassnamnet som 'sel'.

c) Den andra @FindBy med XPath har en ankartagg vars id är ' flik5 ”. Det finns bara ett element som identifierats som svar på sökningen som är grundläggande.
Se ögonblicksbilden nedan:

När nseindia.com-testet utfördes fick vi räkningen av element som söktes efter.
@FindAll som 3. Elementen för findallvalue när de visas var: Grundläggande som 0thindexelement, orderbok som 1stindexelement och Fundamentals igen som 2ndindexelement. Vi har redan lärt oss att @FindAll identifierar element för varje @FindBy-kriterium separat.
Enligt samma protokoll, för den första kriteriesökningen, dvs. className = ”sel”, identifierade den två element som uppfyllde villkoret och det hämtade 'Fundamentals' och 'Order Book'.
Sedan flyttade den till nästa @ FindBy-kriterier och enligt den xpath som gavs för den andra @ FindBy kunde den hämta elementet 'Fundamentals'. Det är därför det äntligen identifierade tre element.
Således får det inte elementen som uppfyller något av @FindBy-villkoren men det hanterar separat var och en av @FindBy och identifierar elementen på samma sätt. I det aktuella exemplet såg vi också att det inte ser om elementen är unika ( T.ex. Elementet 'Fundamentals' i detta fall som visas två gånger som en del av resultatet av de två @FindBy-kriterierna)
# 3) Här utarbetar vi arbetet med @FindBys-anteckningen som kommer att avse listan över webbelement med namnet findbysvalue. Även här söker det första @ FindBy-kriteriet efter element med className = ’sel’ och det andra @ FindBy-kriteriet söker efter ett specifikt element med xpath = “// a (@ id =” tab5 ”).
Nu när vi vet är de element som identifierats för det första @FindBy-villkoret 'Fundamentals' och 'Order Book' och det andra @FindBy-kriteriet är 'Fundamentals'.
Så, hur kommer @FindBys resulterande att vara annorlunda än @FindAll? Vi lärde oss i föregående avsnitt att @FindBys motsvarar AND-villkorlig operatör och därför letar det efter ett element eller en lista över element som uppfyller alla @FindBy-villkor.
Enligt vårt nuvarande exempel är värdet 'Fundamentals' det enda elementet som har class = 'sel' och id = 'tab5', vilket uppfyller båda villkoren. Detta är anledningen till att @FindBys-storlek i testbox är 1 och den visar värdet som 'Grundläggande'.
Caching The Elements In Pagefactory
Varje gång en sida laddas, letas alla element på sidan upp igen genom att anropa ett samtal via @FindBy eller driver.findElement () och det söks nya element på sidan.
Det mesta av tiden när elementen är dynamiska eller fortsätter att förändras under körning, särskilt om de är AJAX-element, är det verkligen meningsfullt att det med varje sidbelastning görs en ny sökning efter alla element på sidan.
När webbsidan har statiska element kan cachning av elementet hjälpa på flera sätt. När elementen är cachade behöver den inte hitta elementen igen när sidan laddas, utan kan referera till det cachade elementförvaret. Detta sparar mycket tid och höjer bättre prestanda.
Pagefactory tillhandahåller denna funktion för att cacha elementen med en kommentar @CacheLookUp .
Anmärkningen ber föraren att använda samma instans av lokaliseraren från DOM för elementen och att inte söka igen medan initElements-metoden för pagefactory på ett framträdande sätt bidrar till att lagra det cachade statiska elementet. Initialerna gör elementens cachingjobb.
Detta gör pagefactory-konceptet speciellt över det vanliga designmönstret för sidobjekt. Den har sina egna fördelar och nackdelar som vi kommer att diskutera lite senare. Till exempel är inloggningsknappen på Facebook-hemsidan ett statiskt element som kan cachas och är ett idealiskt element att cachas.
Låt oss nu titta på hur man implementerar kommentaren @CacheLookUp
Du måste först importera ett paket för Cachelookup enligt nedan:
import org.openqa.selenium.support.CacheLookup
Nedan är kodavsnittet som visar definitionen av ett element med hjälp av @CacheLookUp. Så snart UniqueElement söks för första gången lagrar initElement () den cachade versionen av elementet så att nästa gång drivrutinen inte letar efter elementet istället refererar den till samma cache och utför åtgärden på elementet till höger bort.
@FindBy(id = 'unique') @CacheLookup private WebElement UniqueElement;
Låt oss nu se igenom ett faktiskt program för hur åtgärder på det cachade webbelementet är snabbare än det på det icke-cachade webbelementet:
Förbättra nseindia.com-programmet ytterligare Jag har skrivit en annan ny metod monitorPerformance () där jag skapar ett cachat element för sökrutan och ett icke-cachat element för samma sökruta.
Sedan försöker jag få elementets tagnamn 3000 gånger för både cachat och icke-cachat element och försöker mäta den tid det tar att slutföra uppgiften av både cachat och icke cachat element.
Jag har funderat 3000 gånger så att vi kan se en synlig skillnad i tidsinställningarna för de två. Jag förväntar mig att det cachade elementet ska slutföra att få tagnamnet 3000 gånger på kortare tid jämfört med det för det icke-cachade elementet.
Vi vet nu varför det cachade elementet ska fungera snabbare, det vill säga att drivrutinen uppmanas att inte slå upp elementet efter den första sökningen utan att fortsätta arbeta direkt med det och så är det inte fallet med det icke-cachade elementet där elementets sökning är alla 3000 gånger och sedan utförs åtgärden på den.
Nedan är koden för metoden 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'); }
Vid körning ser vi resultatet nedan i konsolfönstret:
Enligt resultatet slutförs uppgiften på det icke-cachade elementet i 82 sekunder medan den tid det tog att slutföra uppgiften på det cachade elementet bara var 37 sekunder. Detta är verkligen en synlig skillnad i responstiden för både det cachade och icke-cachade elementet.

F # 7) Vilka är för- och nackdelarna med kommentaren @CacheLookUp i Pagefactory-konceptet?
Svar:
Fördelar @CacheLookUp och situationer möjliga för dess användning:
@CacheLookUp är möjligt när elementen är statiska eller inte ändras alls medan sidan laddas. Sådana element ändrar inte körtiden. I sådana fall är det lämpligt att använda anteckningen för att förbättra den totala hastigheten för testkörningen.
Nackdelar med kommentaren @CacheLookUp:
Den största nackdelen med att ha cachade element med anteckningen är rädslan för att få StaleElementReferenceExceptions ofta.
Dynamiska element uppdateras ganska ofta med dem som är mottagliga för att förändras snabbt under några sekunder eller minuter av tidsintervallet.
Nedan följer några sådana fall av dynamiska element:
- Att ha ett stoppur på webbsidan som håller timern uppdaterad varje sekund.
- En ram som ständigt uppdaterar väderrapporten.
- En sida som rapporterar Sensex-uppdateringarna live.
Dessa är inte idealiska eller genomförbara för användningen av kommentaren @CacheLookUp alls. Om du gör det riskerar du att få undantaget StaleElementReferenceExceptions.
Vid cachning av sådana element ändras elementens DOM under testkörning, men drivrutinen letar efter den version av DOM som redan var lagrad under cachningen. Detta gör att det inaktuella elementet ska letas upp av föraren som inte längre finns på webbsidan. Det är därför StaleElementReferenceException kastas.
Fabriksklasser:
Pagefactory är ett koncept som bygger på flera fabriksklasser och gränssnitt. Vi kommer att lära oss några fabriksklasser och gränssnitt här i det här avsnittet. Få av vilka vi kommer att titta på är AjaxElementLocatorFactory , ElementLocatorFactory och StandardElementFactory.
Har vi någonsin undrat om Pagefactory ger något sätt att införliva Implicit eller Explicit vänta på elementet tills ett visst villkor är uppfyllt ( Exempel: Tills ett element är synligt, aktiverat, klickbart etc.)? Om ja, här är ett lämpligt svar på det.
AjaxElementLocatorFactory är en av de betydande bidragsgivarna bland alla fabriksklasser. Fördelen med AjaxElementLocatorFactory är att du kan tilldela ett tidselementvärde för ett webbelement till objektets sidklass.
Även om Pagefactory inte tillhandahåller en uttrycklig väntefunktion, finns det dock en variant för att implicit vänta med klassen AjaxElementLocatorFactory . Denna klass kan användas införlivad när applikationen använder Ajax-komponenter och element.
Så här implementerar du det i koden. När vi använder metoden initElements () inom konstruktören kan vi använda AjaxElementLocatorFactory för att ge en implicit väntan på elementen.
PageFactory.initElements(driver, this); can be replaced with PageFactory.initElements( new AjaxElementLocatorFactory(driver, 20), this);
Ovanstående andra rad i koden innebär att föraren ska ställa in en timeout på 20 sekunder för alla element på sidan när var och en av dess laddningar och om något av elementet inte hittas efter en väntan på 20 sekunder kastas 'NoSuchElementException' för det saknade elementet.
Du kan också definiera väntetiden enligt nedan:
public pageFactoryClass(WebDriver driver) { ElementLocatorFactory locateMe = new AjaxElementLocatorFactory(driver, 30); PageFactory.initElements(locateMe, this); this.driver = driver; }
Ovanstående kod fungerar perfekt eftersom klassen AjaxElementLocatorFactory implementerar gränssnittet ElementLocatorFactory.
Här hänvisar föräldragränssnittet (ElementLocatorFactory) till objektet för barnklassen (AjaxElementLocatorFactory). Därför används Java-konceptet 'upcasting' eller 'runtime polymorphism' när man tilldelar en timeout med AjaxElementLocatorFactory.
När det gäller hur det fungerar tekniskt skapar AjaxElementLocatorFactory först en AjaxElementLocator med en SlowLoadableComponent som kanske inte har slutfört laddningen när belastningen () återvänder. Efter ett samtal för att ladda () bör metoden isLoaded () fortsätta att misslyckas tills komponenten har laddats helt.
Med andra ord kommer alla element att slås upp nytt varje gång när ett element nås i koden genom att anropa ett samtal till locator.findElement () från klassen AjaxElementLocator som sedan tillämpar en timeout tills den laddas genom SlowLoadableComponent-klassen.
Efter att ha tilldelat timeout via AjaxElementLocatorFactory kommer elementen med @CacheLookUp-anteckningen inte längre att cachas eftersom annoteringen ignoreras.
Det finns också en variation i hur du kan ring initiativ () metod och hur du borde inte ring AjaxElementLocatorFactory för att tilldela timeout för ett element.
# 1) Du kan också ange ett elementnamn istället för drivrutinsobjektet som visas nedan i metoden initElements ():
PageFactory.initElements( , this);
initElements () -metoden i ovanstående variant anropar internt ett anrop till klassen DefaultElementFactory och DefaultElementFactory's konstruktör accepterar SearchContext-gränssnittsobjektet som en inmatningsparameter. Webbdrivrutinobjekt och ett webbelement tillhör båda SearchContext-gränssnittet.
I detta fall initialiseras metoden initElements () i förväg endast till det nämnda elementet och inte alla element på webbsidan kommer att initialiseras.
#två) Men här är en intressant vridning mot detta faktum som anger hur du inte ska ringa AjaxElementLocatorFactory-objekt på ett specifikt sätt. Om jag använder ovanstående variant av initElements () tillsammans med AjaxElementLocatorFactory, kommer det att misslyckas.
Exempel: Nedanstående kod, dvs att skicka elementnamn istället för drivarobjekt till AjaxElementLocatorFactory-definitionen, kommer inte att fungera eftersom konstruktören för AjaxElementLocatorFactory-klassen tar endast webbdrivrutinobjekt som inmatningsparameter och därmed fungerar SearchContext-objektet med webbelement inte för det.
PageFactory.initElements(new AjaxElementLocatorFactory(, 10), this);
F # 8) Är det möjligt att använda sidfabriken över det vanliga mönstret för sidobjektdesign?
Svar: Det här är den viktigaste frågan som människor har och det var därför jag tänkte ta itu med det i slutet av handledningen. Vi känner nu till “in och ut” om Pagefactory med utgångspunkt från dess begrepp, noteringar som används, ytterligare funktioner som stöds, implementering via kod, fördelar och nackdelar.
Ändå förblir vi med denna väsentliga fråga att om sidfabrik har så många bra saker, varför ska vi inte hålla fast vid dess användning.
Pagefactory kommer med konceptet CacheLookUp som vi såg inte är möjligt för dynamiska element som värden för elementet uppdateras ofta. Så, sidfabrik utan CacheLookUp, är det bra att gå? Ja, om xpaths är statiska.
Men undergången är att den moderna tidsapplikationen är fylld med tunga dynamiska element där vi vet att sidobjektdesign utan sidfabrik fungerar i slutändan bra men fungerar sidfabrikskonceptet lika bra med dynamiska xpaths? Kanske inte. Här är ett snabbt exempel:
På nseindia.com-webbsidan ser vi en tabell enligt nedan.

Tabellen xpath är
'//*(@id='tab9Content')/table/tbody/tr(+count+)/td(1)'
Vi vill hämta värden från varje rad för den första kolumnen ”Köp Antal”. För att göra detta måste vi öka radräknaren men kolumnindexet kommer att förbli 1. Det finns inget sätt att vi kan skicka denna dynamiska XPath i @FindBy-anteckningen eftersom anteckningen accepterar värden som är statiska och ingen variabel kan skickas vidare den.
Här misslyckas sidfabriken helt medan den vanliga POM fungerar bra med den. Du kan enkelt använda en for loop för att öka radindex med sådana dynamiska xpaths i metoden driver.findElement ().
Slutsats
Page Object Model är ett designkoncept eller -mönster som används i Selenium-automatiseringsramen.
Att namnge konvektion av metoder är användarvänligt i Page Object Model. Koden i POM är lätt att förstå, återanvändbar och underhållbar. Om det sker någon förändring i webbelementet i POM räcker det att göra ändringarna i sin respektive klass snarare än att redigera alla klasser.
Pagefactory precis som den vanliga POM är ett underbart koncept att tillämpa. Vi måste dock veta var den vanliga POM är genomförbar och var Pagefactory passar bra. I de statiska applikationerna (där både XPath och element är statiska) kan Pagefactory implementeras på ett frikostigt sätt med ytterligare fördelar med bättre prestanda.
Alternativt, när applikationen involverar både dynamiska och statiska element, kan du ha en blandad implementering av pom med Pagefactory och det utan Pagefactory enligt genomförbarheten för varje webbelement.
Författare: Denna handledning har skrivits av Shobha D. Hon arbetar som projektledare och har 9+ års erfarenhet av manuell, automatisering (Selen, IBM Rational Functional Tester, Java) och API-testning (SOAPUI och vara säker på Java) .
Nu över till dig för vidare implementering av Pagefactory.
Happy Exploring !!!
=> Besök här för att lära dig selen från repor.
Rekommenderad läsning
- 30+ bästa selen-självstudier: Lär dig selen med riktiga exempel
- Effektiv skriptning av selen och felsökning av scenarier - Selen-handledning # 27
- Felsökning av selenskript med loggar (Log4j-handledning) - Selen-handledning # 26
- Introduktion till JUnit Framework and Its Use in Selenium Script - Selenium Tutorial # 11
- 7 faktorer som påverkar testuppskattning av Selen Automation Project - Selen Tutorial # 32
- Påståenden i selen med Junit och TestNG Frameworks
- Hur man använder TestNG Framework för att skapa Selen-skript - TestNG Selen Tutorial # 12
- Lär dig hur du använder TestNG-anteckningar i selen (med exempel)