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().

Sidobjektmodell

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

Sidobjektmodell

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.

Sidobjektmodell

Fördelar med POM

  1. 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å.
  2. 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.
  3. Koden blir mindre och optimerad på grund av de återanvändbara sidmetoderna i POM-klasserna.
  4. 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.

Implementera POM

Komplett exempel

Testfall: Gå till Guru99 Demo Site.

Steg 1) Gå till Guru99 Demo Site

Implementera POM

Steg 2) På hemsidan kontrollera texten "Guru99 Bank" är närvarande

Implementera POM

Steg 3) Logga in i applikationen

Implementera POM

Steg 4) Kontrollera att hemsidan innehåller text som "Manager Id: demo"

Implementera POM

Här har vi att göra med 2 sidor

  1. Logga sidan
  2. 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

Page Factory In Selenium

@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:

Page Factory i Selenium

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.

AjaxElement Locator Factory

Sammanfattning

  1. Sidobjektsmodell i Selenium WebDriver är ett designmönster för Object Repository.
  2. Selenium sidobjektmodell skapar vår testkod underhållbar, återanvändbar.
  3. Page Factory är ett optimerat sätt att skapa objektförråd i ramkonceptet Page Object Model.
  4. 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