Mô hình đối tượng trang & Nhà máy trong Selenium

Mô hình đối tượng trang là gì?

Mô hình đối tượng trang (POM) là một mẫu thiết kế, được sử dụng phổ biến trong tự động hóa thử nghiệm nhằm tạo Kho lưu trữ đối tượng cho các thành phần giao diện người dùng web. Ưu điểm của mô hình là giảm sự trùng lặp mã và cải thiện việc bảo trì thử nghiệm.

Theo mô hình này, đối với mỗi trang web trong ứng dụng, cần có một Lớp trang tương ứng. Lớp Trang này sẽ xác định các WebElements của trang web đó và cũng chứa các phương thức Trang thực hiện các thao tác trên các WebElements đó. Tên của các phương thức này phải được đặt theo nhiệm vụ mà chúng đang thực hiện, tức là nếu trình tải đang đợi cổng thanh toán xuất hiện, thì tên phương thức POM có thể là waitForPaymentScreenDisplay().

Mô hình đối tượng trang

Tại sao mô hình đối tượng trang?

Bắt đầu Tự động hóa giao diện người dùng trong Selenium WebDriver KHÔNG phải là một nhiệm vụ khó khăn. Bạn chỉ cần tìm các phần tử, thực hiện các thao tác trên đó.

Hãy xem xét tập lệnh đơn giản này để đăng nhập vào một trang web

Mô hình đối tượng trang

Như bạn có thể quan sát, tất cả những gì chúng ta đang làm là tìm các phần tử và điền giá trị cho các phần tử đó.

Đây là một kịch bản nhỏ. Bảo trì tập lệnh có vẻ dễ dàng. Nhưng theo thời gian, bộ thử nghiệm sẽ phát triển. Khi bạn thêm ngày càng nhiều dòng vào mã của mình, mọi thứ trở nên khó khăn hơn.

Vấn đề chính với việc bảo trì tập lệnh là nếu 10 tập lệnh khác nhau đang sử dụng cùng một thành phần trang, thì với bất kỳ thay đổi nào trong thành phần đó, bạn cần phải thay đổi tất cả 10 tập lệnh. Việc này tốn thời gian và dễ xảy ra lỗi.

Cách tiếp cận tốt hơn để bảo trì tập lệnh là tạo một tệp lớp riêng biệt để tìm các phần tử web, điền hoặc xác minh chúng. Lớp này có thể được sử dụng lại trong tất cả các tập lệnh sử dụng phần tử đó. Trong tương lai, nếu có thay đổi trong thành phần web, chúng ta cần thực hiện thay đổi chỉ trong 1 tệp lớp chứ không phải 10 tập lệnh khác nhau.

Cách tiếp cận này được gọi là Mô hình đối tượng trang trong Selenium. Nó giúp làm cho mã dễ đọc hơn, dễ bảo trì hơn và có thể tái sử dụng hơn.

Mô hình đối tượng trang

Ưu điểm của POM

  1. Mẫu thiết kế đối tượng trang cho biết các hoạt động và luồng trong giao diện người dùng phải được tách biệt khỏi quá trình xác minh. Khái niệm này làm cho mã của chúng tôi sạch hơn và dễ hiểu hơn.
  2. Lợi ích thứ hai là kho đối tượng độc lập với các trường hợp thử nghiệm, vì vậy chúng ta có thể sử dụng cùng một kho đối tượng cho các mục đích khác nhau bằng các công cụ khác nhau. Ví dụ: chúng ta có thể tích hợp Mô hình đối tượng trang trong Selenium với TestNG/JUnit cho chức năng Kiểm tra và đồng thời với JBehave/Cucumber cho việc kiểm tra chấp nhận.
  3. Mã trở nên ít hơn và được tối ưu hóa nhờ các phương thức trang có thể sử dụng lại trong các lớp POM.
  4. Các phương thức có tên thực tế hơn, có thể dễ dàng ánh xạ với thao tác xảy ra trong giao diện người dùng. tức là nếu sau khi nhấp vào nút, chúng tôi đến trang chủ, tên phương thức sẽ giống như 'gotoHomePage()'.

Triển khai POM như thế nào?

POM đơn giản:

Đó là cấu trúc cơ bản của khung mô hình đối tượng Trang nơi tất cả các Thành phần Web của AUT và phương thức hoạt động trên các Thành phần Web này được duy trì bên trong một tệp lớp. Nhiệm vụ như xác minh phải tách biệt như một phần của Phương thức kiểm tra.

Triển khai POM

Hoàn thành ví dụ

Trường hợp thử nghiệm: Đi tới Trang demo Guru99.

Bước 1) Truy cập Trang demo Guru99

Triển khai POM

Bước 2) Tại trang chủ có dòng chữ kiểm tra “Guru99 Bank”

Triển khai POM

Bước 3) Đăng nhập vào ứng dụng

Triển khai POM

Bước 4) Xác minh rằng Trang chủ có chứa văn bản là “Id Manger: demo”

Triển khai POM

Đây là chúng tôi đang xử lý 2 trang

  1. Đăng nhập Trang
  2. Trang chủ (hiển thị khi bạn đăng nhập)

Theo đó chúng ta tạo 2 POM trong Selenium các lớp học

Trang đăng nhập Guru99 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();        
    }

}

Trang chủ Guru99 POM trong 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 POM đơn giản trong Selenium Kiểm tra trường hợp

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"));

    }

Page Factory là gì Selenium?

Nhà máy trang ở Selenium là một khái niệm khung Mô hình Đối tượng Trang có sẵn dành cho Selenium WebDriver nhưng nó rất tối ưu. Nó được sử dụng để khởi tạo các đối tượng Trang hoặc để khởi tạo chính đối tượng Trang đó. Nó cũng được sử dụng để khởi tạo các phần tử của lớp Trang mà không cần sử dụng “FindElement/s”.

Ở đây cũng vậy, chúng tôi tuân theo khái niệm tách biệt Kho lưu trữ đối tượng trang và Phương thức kiểm tra. Ngoài ra, với sự trợ giúp của lớp PageFactory trong Selenium, chúng tôi sử dụng chú thích @FindBy để tìm WebElement. Chúng tôi sử dụng phương thức initElements để khởi tạo các thành phần web

Trang Nhà máy ở Selenium

@FindBy có thể chấp nhận tagName, một phầnLinkText, tên, linkText, id, css, className, xpath dưới dạng các thuộc tính.

Hãy xem ví dụ tương tự như trên bằng cách sử dụng Page Factory

Trang đăng nhập Guru99 với 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();           

    }

}

Trang chủ Guru99 với Trang 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 với khái niệm Page Factory

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"));

    }

}

Cấu trúc dự án hoàn chỉnh sẽ giống như sơ đồ:

Nhà máy trang ở Selenium

AjaxElementLocatorNhà máy

AjaxElementLocatorNhà máy là một khái niệm tải từng phần của PageFactory trong Selenium. Nó chỉ được sử dụng để tìm các phần tử web khi các phần tử đó được sử dụng trong bất kỳ thao tác nào. Nó chỉ định thời gian chờ cho WebElements cho lớp trang đối tượng. Một trong những ưu điểm chính của việc sử dụng mẫu PageFactory trong Selenium là Lớp AjaxElementLocatorFactory.

Ở đây, khi một thao tác được thực hiện trên một phần tử, việc chờ khả năng hiển thị của nó chỉ bắt đầu từ thời điểm đó. Nếu phần tử không được tìm thấy trong khoảng thời gian nhất định, Trường hợp thử nghiệm việc thực thi sẽ đưa ra ngoại lệ 'NoSuchElementException'.

Nhà máy định vị AjaxElement

Tổng kết

  1. Mô hình đối tượng trang trong Selenium WebDriver là một mẫu thiết kế Kho lưu trữ đối tượng.
  2. Selenium mô hình đối tượng trang tạo mã thử nghiệm của chúng tôi có thể duy trì và tái sử dụng.
  3. Page Factory là một cách tối ưu hóa để tạo kho lưu trữ đối tượng trong khái niệm khung Mô hình đối tượng trang.
  4. AjaxElementLocatorFactory là một khái niệm tải từng phần trong Page Factory - mẫu thiết kế đối tượng trang để chỉ xác định WebElements khi chúng được sử dụng trong bất kỳ hoạt động nào.

Tải về Selenium Tệp dự án cho bản demo trong hướng dẫn này

Tìm hiểu thêm về PNV Xem tiếp