Page Object Model (POM) & Page Factory i Selenium

Hvad er sideobjektmodel?

Sideobjektmodel (POM) er et designmønster, populært brugt i testautomatisering, der skaber Object Repository til web-UI-elementer. Fordelen ved modellen er, at den reducerer kodeduplikering og forbedrer testvedligeholdelse.

Under denne model skal der for hver webside i applikationen være en tilsvarende sideklasse. Denne sideklasse identificerer webelementerne på den pågældende webside og indeholder også sidemetoder, som udfører handlinger på disse webelementer. Navnet på disse metoder skal angives i henhold til den opgave, de udfører, dvs. hvis en indlæser venter på, at betalingsgatewayen vises, kan POM-metodenavnet være waitForPaymentScreenDisplay().

Sideobjektmodel

Hvorfor sideobjektmodel?

Start af en UI-automatisering i Selenium WebDriver er IKKE en svær opgave. Du skal bare finde elementer, udføre operationer på det.

Overvej dette enkle script til at logge ind på et websted

Sideobjektmodel

Som du kan se, er alt, hvad vi gør, at finde elementer og udfylde værdier for disse elementer.

Dette er et lille script. Scriptvedligeholdelse ser let ud. Men med tiden vil testsuiten vokse. Efterhånden som du tilføjer flere og flere linjer til din kode, bliver tingene svære.

Det største problem med scriptvedligeholdelse er, at hvis 10 forskellige scripts bruger det samme sideelement, med enhver ændring i det element, skal du ændre alle 10 scripts. Dette er tidskrævende og fejludsat.

En bedre tilgang til scriptvedligeholdelse er at oprette en separat klassefil, som kan finde webelementer, udfylde dem eller verificere dem. Denne klasse kan genbruges i alle scripts ved hjælp af dette element. Hvis der fremover er en ændring i webelementet, skal vi lave ændringen i kun 1 klassefil og ikke 10 forskellige scripts.

Denne tilgang kaldes Page Object Model i Selenium. Det hjælper med at gøre koden mere læsbar, vedligeholdelsesvenlig og genbrugelig.

Sideobjektmodel

Fordele ved POM

  1. Page Object Design Pattern siger, at operationer og flows i brugergrænsefladen skal adskilles fra verifikation. Dette koncept gør vores kode renere og nem at forstå.
  2. Den anden fordel er, at objektlageret er uafhængigt af testcases, så vi kan bruge det samme objektlager til et andet formål med forskellige værktøjer. For eksempel kan vi integrere Page Object Model i Selenium med TestNG/JUnit til funktionel Test og samtidig med JBehave/Cucumber til accepttest.
  3. Koden bliver mindre og optimeret på grund af de genanvendelige sidemetoder i POM-klasserne.
  4. Metoder får mere realistiske navne, som nemt kan kortlægges med operationen, der sker i brugergrænsefladen. dvs. hvis vi lander på startsiden efter at have klikket på knappen, vil metodenavnet være som 'gotoHomePage()'.

Hvordan implementerer man POM?

Simpel POM:

Det er den grundlæggende struktur af sideobjektmodelramme, hvor alle webelementer i AUT og metoden, der fungerer på disse webelementer, vedligeholdes inde i en klassefil. En opgave som verifikation bør være adskilt som en del af testmetoder.

Implementer POM

Komplet eksempel

test sag: Gå til Guru99 Demo Site.

Trin 1) Gå til Guru99 Demo Site

Implementer POM

Trin 2) Tjek teksten "Guru99 Bank" på hjemmesiden

Implementer POM

Trin 3) Log ind på applikationen

Implementer POM

Trin 4) Bekræft, at hjemmesiden indeholder tekst som "Manger Id: demo"

Implementer POM

Her har vi at gøre med 2 sider

  1. Login-side
  2. Hjemmeside (vises, når du logger ind)

Derfor opretter vi 2 POM i Selenium klasser

Guru99 Login side 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 Hjemmeside 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 Simpel POM ind Selenium Test tilfælde

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("http://demo.guru99.com/V4/");

    }

    /**

     * This test case will login in http://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"));

    }

Hvad er Page Factory i Selenium?

Page Factory i Selenium er et indbygget Page Object Model-rammekoncept til Selenium WebDriver, men den er meget optimeret. Det bruges til initialisering af sideobjekter eller til at instansiere selve sideobjektet. Det bruges også til at initialisere sideklasseelementer uden at bruge "FindElement/s."

Også her følger vi konceptet om adskillelse af Page Object Repository og testmetoder. Derudover med hjælp fra klassen PageFactory i Selenium, bruger vi anmærkninger @FindBy for at finde WebElement. Vi bruger initElements-metoden til at initialisere webelementer

Side Factory In Selenium

@FindBy kan acceptere tagName, partialLinkText, name, linkText, id, css, className, xpath som attributter.

Lad os se på det samme eksempel som ovenfor ved at bruge Page Factory

Guru99 Login-side 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 Hjemmeside 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("http://demo.guru99.com/V4/");

    }

    /**

     * This test go to http://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"));

    }

}

Komplet projektstruktur vil se ud som diagrammet:

Page Factory i Selenium

AjaxElementLocatorFactory

AjaxElementLocatorFactory er et dovent indlæsningskoncept af PageFactory i Selenium. Det bruges kun til at finde webelementerne, når elementerne bruges i enhver operation. Den tildeler en timeout for WebElements til objektsideklassen. En af de vigtigste fordele ved at bruge mønsteret PageFactory i Selenium er AjaxElementLocatorFactory Class.

Her, når en operation udføres på et element, starter ventetiden på dets synlighed kun fra det øjeblik. Hvis elementet ikke findes i det givne tidsinterval, Test sag udførelse vil kaste 'NoSuchElementException' undtagelse.

AjaxElement Locator Factory

Resumé

  1. Sideobjektmodel i Selenium WebDriver er et Object Repository-designmønster.
  2. Selenium sideobjektmodel skaber vores testkode, der kan vedligeholdes, genbruges.
  3. Page Factory er en optimeret måde at oprette objektlager i Page Object Model framework-konceptet.
  4. AjaxElementLocatorFactory er et lazy load-koncept i Page Factory – sideobjektdesignmønster til kun at identificere WebElements, når de bruges i enhver operation.

Download Selenium Projektfiler til demoen i denne vejledning

Læs mere Læs mere