Sidobjektsmodell och fabrik i Selenium
Vad är Page Object Model?
Sidobjektsmodell (POM) är ett designmönster, populärt använt i testautomatisering som skapar Object Repository för webbgränssnittselement. Fördelen med modellen är att den minskar kodduplicering och förbättrar testunderhållet.
Under denna modell bör det finnas en motsvarande sidklass för varje webbsida i applikationen. Denna sidklass kommer att identifiera webbelementen för den webbsidan och innehåller även sidmetoder som utför operationer på dessa webbelement. Namnet på dessa metoder bör anges i enlighet med uppgiften de utför, dvs om en laddare väntar på att betalningsporten ska dyka upp kan POM-metodens namn vara waitForPaymentScreenDisplay().
Varför Page Object Model?
Starta en UI-automatisering i Selenium WebDriver är INTE en svår uppgift. Du behöver bara hitta element, utföra operationer på det.
Överväg detta enkla skript för att logga in på en webbplats
Som du kan se är allt vi gör att hitta element och fylla i värden för dessa element.
Detta är ett litet manus. Skriptunderhåll ser enkelt ut. Men med tiden kommer testsviten att växa. När du lägger till fler och fler rader i din kod blir det tufft.
Det största problemet med skriptunderhåll är att om 10 olika skript använder samma sidelement, med någon ändring i det elementet, måste du ändra alla 10 skript. Detta är tidskrävande och felbenäget.
En bättre metod för underhåll av skript är att skapa en separat klassfil som kan hitta webbelement, fylla dem eller verifiera dem. Den här klassen kan återanvändas i alla skript som använder det elementet. I framtiden, om det blir en förändring i webbelementet, behöver vi göra ändringen i bara 1 klassfil och inte 10 olika skript.
Detta tillvägagångssätt kallas Page Object Model i Selenium. Det hjälper till att göra koden mer läsbar, underhållbar och återanvändbar.
Fördelar med POM
- Page Object Design Pattern säger att operationer och flöden i användargränssnittet bör separeras från verifiering. Detta koncept gör vår kod renare och lätt att förstå.
- Den andra fördelen är att objektförrådet är oberoende av testfall, så vi kan använda samma objektförråd för ett annat ändamål med olika verktyg. Till exempel kan vi integrera Page Object Model i Selenium med TestNG/JUnit för funktionell Testning och samtidigt med JBehave/Cucumber för acceptanstestning.
- Koden blir mindre och optimerad på grund av de återanvändbara sidmetoderna i POM-klasserna.
- Metoder får mer realistiska namn som enkelt kan mappas med operationen som sker i UI. dvs om vi landar på startsidan efter att ha klickat på knappen kommer metodnamnet att vara som 'gotoHomePage()'.
Hur implementerar man POM?
Enkel POM:
Det är den grundläggande strukturen för sidobjektmodellens ramverk där alla webbelement i AUT och metoden som fungerar på dessa webbelement underhålls i en klassfil. En uppgift som verifiering bör vara separat som en del av testmetoder.
Komplett exempel
Testfall: Gå till Guru99 Demo Site.
Steg 1) Gå till Guru99 Demo Site
Steg 2) På hemsidan kontrollera texten "Guru99 Bank" är närvarande
Steg 3) Logga in i applikationen
Steg 4) Kontrollera att hemsidan innehåller text som "Manager Id: demo"
Här har vi att göra med 2 sidor
- Logga sidan
- Hemsida (visas när du loggar in)
Följaktligen skapar vi 2 POM in Selenium klasser
Guru99 Inloggningssida POM
package pages; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; public class Guru99Login { WebDriver driver; By user99GuruName = By.name("uid"); By password99Guru = By.name("password"); By titleText =By.className("barone"); By login = By.name("btnLogin"); public Guru99Login(WebDriver driver){ this.driver = driver; } //Set user name in textbox public void setUserName(String strUserName){ driver.findElement(user99GuruName).sendKeys(strUserName); } //Set password in password textbox public void setPassword(String strPassword){ driver.findElement(password99Guru).sendKeys(strPassword); } //Click on login button public void clickLogin(){ driver.findElement(login).click(); } //Get the title of Login Page public String getLoginTitle(){ return driver.findElement(titleText).getText(); } /** * This POM method will be exposed in test case to login in the application * @param strUserName * @param strPasword * @return */ public void loginToGuru99(String strUserName,String strPasword){ //Fill user name this.setUserName(strUserName); //Fill password this.setPassword(strPasword); //Click Login button this.clickLogin(); } }
Guru99 Hemsida POM in Selenium
package pages; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; public class Guru99HomePage { WebDriver driver; By homePageUserName = By.xpath("//table//tr[@class='heading3']"); public Guru99HomePage(WebDriver driver){ this.driver = driver; } //Get the User name from Home Page public String getHomePageDashboardUserName(){ return driver.findElement(homePageUserName).getText(); } }
Guru99 Enkel POM in Selenium Testfall
package test; import java.util.concurrent.TimeUnit; import org.openqa.selenium.WebDriver; import org.openqa.selenium.firefox.FirefoxDriver; import org.testng.Assert; import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; import pages.Guru99HomePage; import pages.Guru99Login; public class Test99GuruLogin { String driverPath = "C:\\geckodriver.exe"; WebDriver driver; Guru99Login objLogin; Guru99HomePage objHomePage; @BeforeTest public void setup(){ System.setProperty("webdriver.gecko.driver", driverPath); driver = new FirefoxDriver(); driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS); driver.get("https://demo.guru99.com/V4/"); } /** * This test case will login in https://demo.guru99.com/V4/ * Verify login page title as guru99 bank * Login to application * Verify the home page using Dashboard message */ @Test(priority=0) public void test_Home_Page_Appear_Correct(){ //Create Login Page object objLogin = new Guru99Login(driver); //Verify login page title String loginPageTitle = objLogin.getLoginTitle(); Assert.assertTrue(loginPageTitle.toLowerCase().contains("guru99 bank")); //login to application objLogin.loginToGuru99("mgr123", "mgr!23"); // go the next page objHomePage = new Guru99HomePage(driver); //Verify home page Assert.assertTrue(objHomePage.getHomePageDashboardUserName().toLowerCase().contains("manger id : mgr123")); }
Vad är Page Factory i Selenium?
Page Factory i Selenium är ett inbyggt Page Object Model-ramverkskoncept för Selenium WebDriver men den är väldigt optimerad. Den används för initiering av sidobjekt eller för att instansiera själva sidobjektet. Det används också för att initiera sidklasselement utan att använda "FindElement/s."
Även här följer vi konceptet med separation av Page Object Repository och testmetoder. Dessutom med hjälp av klassen PageFactory i Selenium, vi använder anteckningar @FindBy för att hitta WebElement. Vi använder metoden initElements för att initiera webbelement
@FindBy kan acceptera tagName, partialLinkText, name, linkText, id, css, className, xpath som attribut.
Låt oss titta på samma exempel som ovan med Page Factory
Guru99 Inloggningssida med Page Factory
package PageFactory; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.support.FindBy; import org.openqa.selenium.support.PageFactory; public class Guru99Login { /** * All WebElements are identified by @FindBy annotation */ WebDriver driver; @FindBy(name="uid") WebElement user99GuruName; @FindBy(name="password") WebElement password99Guru; @FindBy(className="barone") WebElement titleText; @FindBy(name="btnLogin") WebElement login; public Guru99Login(WebDriver driver){ this.driver = driver; //This initElements method will create all WebElements PageFactory.initElements(driver, this); } //Set user name in textbox public void setUserName(String strUserName){ user99GuruName.sendKeys(strUserName); } //Set password in password textbox public void setPassword(String strPassword){ password99Guru.sendKeys(strPassword); } //Click on login button public void clickLogin(){ login.click(); } //Get the title of Login Page public String getLoginTitle(){ return titleText.getText(); } /** * This POM method will be exposed in test case to login in the application * @param strUserName * @param strPasword * @return */ public void loginToGuru99(String strUserName,String strPasword){ //Fill user name this.setUserName(strUserName); //Fill password this.setPassword(strPasword); //Click Login button this.clickLogin(); } }
Guru99 Hemsida med Page Factory
package PageFactory; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.support.FindBy; import org.openqa.selenium.support.PageFactory; public class Guru99HomePage { WebDriver driver; @FindBy(xpath="//table//tr[@class='heading3']") WebElement homePageUserName; public Guru99HomePage(WebDriver driver){ this.driver = driver; //This initElements method will create all WebElements PageFactory.initElements(driver, this); } //Get the User name from Home Page public String getHomePageDashboardUserName(){ return homePageUserName.getText(); } }
Guru99 TestCase med Page Factory-koncept
package test; import java.util.concurrent.TimeUnit; import org.openqa.selenium.WebDriver; import org.openqa.selenium.firefox.FirefoxDriver; import org.testng.Assert; import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; import PageFactory.Guru99HomePage; import PageFactory.Guru99Login; public class Test99GuruLoginWithPageFactory { String driverPath = "C:\\geckodriver.exe"; WebDriver driver; Guru99Login objLogin; Guru99HomePage objHomePage; @BeforeTest public void setup(){ System.setProperty("webdriver.gecko.driver", driverPath); driver = new FirefoxDriver(); driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS); driver.get("https://demo.guru99.com/V4/"); } /** * This test go to https://demo.guru99.com/V4/ * Verify login page title as guru99 bank * Login to application * Verify the home page using Dashboard message */ @Test(priority=0) public void test_Home_Page_Appear_Correct(){ //Create Login Page object objLogin = new Guru99Login(driver); //Verify login page title String loginPageTitle = objLogin.getLoginTitle(); Assert.assertTrue(loginPageTitle.toLowerCase().contains("guru99 bank")); //login to application objLogin.loginToGuru99("mgr123", "mgr!23"); // go the next page objHomePage = new Guru99HomePage(driver); //Verify home page Assert.assertTrue(objHomePage.getHomePageDashboardUserName().toLowerCase().contains("manger id : mgr123")); } }
Komplett projektstruktur kommer att se ut som i diagrammet:
AjaxElementLocatorFactory
AjaxElementLocatorFactory är ett lat laddningskoncept av PageFactory i Selenium. Den används för att hitta webbelementen endast när elementen används i någon operation. Den tilldelar en timeout för WebElements till objektsidklassen. En av de viktigaste fördelarna med att använda mönstret PageFactory i Selenium är AjaxElementLocatorFactory Class.
Här, när en operation utförs på ett element, börjar väntan på dess synlighet endast från det ögonblicket. Om elementet inte hittas inom det angivna tidsintervallet, Testfall exekvering kommer att kasta 'NoSuchElementException' undantag.
Sammanfattning
- Sidobjektsmodell i Selenium WebDriver är ett designmönster för Object Repository.
- Selenium sidobjektmodell skapar vår testkod underhållbar, återanvändbar.
- Page Factory är ett optimerat sätt att skapa objektförråd i ramkonceptet Page Object Model.
- AjaxElementLocatorFactory är ett lat laddningskoncept i Page Factory – sidobjektdesignmönster för att identifiera WebElements endast när de används i någon operation.
ladda ner Selenium Projektfiler för demon i denna handledning