页面对象模型和工厂 Selenium

⚡ 智能摘要

页面对象模型和页面工厂 Selenium 定义一种结构化的设计模式,用于构建健壮、易维护的测试自动化框架。它强调创建页面特定的类来封装 Web 元素及其行为,从而减少重复代码,提高代码的可读性和可扩展性。 Selenium 测试脚本。

  • 核心理念: 每个应用程序页面都对应一个专用的页面类,其中包含 Web 元素和对其执行的操作,从而实现了 UI 结构和测试逻辑之间的清晰分离。
  • 实施重点: POM 提倡可重用和集中式元素管理——对页面元素的修改只需要在一个类中进行更新,而不是多个脚本。
  • 设计优势: 该模型确保了更清晰、模块化且与工具无关的对象存储库,并且可以与诸如……之类的框架集成。 TestNG, JUnit, Cucumber或者 JBehave。
  • 命名约定: 页面类中的方法必须反映实际的 UI 操作(例如, gotoHomePage()),增强自动化工作流程中的语义清晰度。
  • 增强结构: Page Factory 通过使用以下方式改进 POM @FindBy 注释和 PageFactory.initElements() 用于自动 WebElement 初始化,消除重复操作 findElement 调用。
  • 性能优化: AjaxElementLocatorFactory 引入延迟加载——元素仅在访问时才被定位——提高了执行效率,并能优雅地处理动态页面行为。
  • 结果: 这种统一的方法可以构建出易于维护、易读且可扩展的测试自动化架构,并与现代技术接轨。 Selenium 实践。

页面对象模型

什么是页面对象模型?它的关键组成部分是什么?

页面对象模型 (POM) 是一种设计模式,常用于测试自动化,它为 Web UI 元素创建对象库。该模型的优势在于减少了代码重复并提高了测试维护的便捷性。

在此模型下,应用程序中的每个网页都应该有一个对应的页面类。该页面类将标识该网页的 Web 元素,并包含对这些 Web 元素执行操作的页面方法。这些方法的名称应与其执行的任务相符,例如,如果加载器正在等待支付网关出现,则 POM 方法名称可以命名为 waitForPaymentScreenDisplay()。

页面对象模型的关键组成部分

  • 页面类别: 将每个网页表示为一个单独的类。
  • 定位器: 使用 ID、XPath 或 CSS 选择器识别网页元素。
  • 方法: 包含对 .page 元素执行的操作或操作。
  • 可重用性: Promo测试代码可重用,且更易于跨测试进行维护。
  • 关注点分离: 为了更好地组织页面结构,使页面结构与测试逻辑保持独立。

页面对象模型

为什么选择页面对象模型?

在 UI 自动化中启动 Selenium 网络驱动程序 这并不是一项艰巨的任务。你只需要找到元素并对它们进行操作即可。

请看这个简单的网站登录脚本。

页面对象模型

正如您所看到的,我们所做的就是查找元素并为这些元素填充值。

这是一个耗时且容易出错的脚本。起初看似简单,但随着测试套件的扩展,管理元素变更就会变得困难。而且随着时间的推移,测试套件还会不断增长。随着代码行数的不断增加,事情会变得越来越棘手。

脚本维护的主要问题是,如果 10 个不同的脚本使用同一个页面元素,那么一旦该元素发生任何变化,您就需要更改所有 10 个脚本。这非常耗时,而且容易出错。

更好的脚本维护方法是创建一个单独的类文件,用于查找网页元素、填充元素或验证元素。这样,多个与同一元素交互的测试脚本就可以重复使用这个类。将来,如果网页元素发生更改,我们只需要修改一个类文件,而无需修改十个不同的脚本。

这种方法在 Selenium它有助于提高代码的可读性、可维护性和可重用性。

 页面对象模型

👉 免费报名参加直播 Selenium 项目

POM的优点

  1. 页面对象设计模式认为 UI 中的操作和流程应该与验证分开。这个概念使我们的代码更简洁、更易于理解。
  2. 第二个好处是对象库独立于测试用例,因此我们可以使用同一个对象库和不同的工具来实现不同的目的。例如,我们可以将页面对象模型集成到…… Selenium - TestNG/JUnit 功能性 测试与验证 同时与 JBehave/Cucumber 进行验收测试。
  3. Code 由于它重用了 POM 类中的页面方法,因此变得更简洁、更优化。
  4. 方法名称更加贴近实际,更容易与用户界面中发生的操作相对应。例如,如果点击按钮后跳转到首页,则方法名称将类似于“gotoHomePage()”。

如何在POM中实现 Selenium?

页面对象模型框架基础结构中的简单 PLog,其中 whereManagereIDElements 的 AUT 操作这些 Web 元素的方法保存在一个 clog 文件中。验证之类的任务应该作为测试方法的一部分单独列出。

实施 POM

完整示例

测试用例: 在MyCAD中点击 软件更新 Guru99 演示站点。

步骤1)前往 Guru99 演示网站

实施 POM

步骤 2)在首页上,检查文本“Guru99银行”在场

实施 POM

步骤 3)登录应用程序

实施 POM

步骤 4)验证主页是否包含文本“Manger Id: demo”

实施 POM

在这个例子中,我们要处理两个页面:

  1. 登录页面
  2. 主页(登录后显示)

因此,我们在 Selenium 类

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 the 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 allows the test case to perform the login operation
     * @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 首页 POM 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 Selenium 测试用例

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("manager id : mgr123"));
    }

Page Factory 是什么 Selenium?

页面工厂 Selenium 是内置的页面对象模型框架概念 Selenium WebDriver 通过注解减少重复的元素查找,而非提高执行速度,从而提升可维护性。它用于初始化 Page 对象或实例化 Page 对象本身。此外,它还用于初始化 Page 类元素,而无需使用“FindElement”方法。

在这里,我们也遵循了页面对象存储库和测试方法分离的概念。此外,借助 Selenium,我们使用注释 @FindBy 查找 WebElement。我们使用 initElements 方法来初始化 Web 元素。

页面工厂 Selenium

@FindBy 可以接受 标签名称、部分链接文本、名称、链接文本、id、css、类名称、xpath 作为属性。

让我们使用 Page Factory 看一下与上面相同的示例

Guru99 使用 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 首页(含页面工厂)

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 个带有页面工厂概念的测试用例

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("manager id : mgr123"));
    }
}

完整的项目结构如下图所示:

页面工厂 Selenium

AjaxElementLocatorFactory

AjaxElementLocatorFactory 是 PageFactory 中的延迟加载概念 Selenium它用于仅在元素用于任何操作时才查找 Web 元素。它为 WebElements 对象页面类设置超时时间。使用 PageFactory 模式的主要优势之一是…… Selenium 是 AjaxElementLocatorFactory 类。

这里,当对某个元素执行操作时,等待其可见性的计时才从那一刻开始。如果在给定的时间间隔内未找到该元素, 测试用例 执行会抛出‘NoSuchElementException’异常。

AjaxElement 定位器工厂

例如:

AjaxElementLocatorFactory factory = new AjaxElementLocatorFactory(driver, 10);
PageFactory.initElements(factory, this);

下载 Selenium 本教程中演示的项目文件

常见问题

页面对象模型是一种设计模式,它……trac将网页元素拆分成单独的类。它通过将用户界面交互与测试逻辑分离来简化自动化测试,从而提高代码清晰度、可扩展性并减少代码重复。

In SeleniumPOM 将每个网页表示为一个包含定位器和操作的专用类。它封装了 UI 元素,使测试脚本能够独立于底层页面结构的更改。

POM并非独立框架,而是一种设计模式。它可以集成到任何自动化框架中,以高效地构建测试,从而确保更好的组织性、可重用性和可维护性。

POM(页面对象模型)是一种设计原则,它将每个网页建模为一个具有已定义定位器和方法的类。它将测试逻辑与用户界面元素解耦,从而提高了可读性、可扩展性和长期可维护性。

POM 定义了页面绝对值的设计结构traction,而 Page Factory 提供注解和方法(@FindBy用于高效初始化网页元素。页面工厂是 POM 的一种实现增强。

POM 将元素定位器和页面操作集中在专用类中。任何 UI 修改都只需要在一个地方进行更新,从而最大限度地减少返工,提高代码重用率,并加快测试维护速度。

是的。人工智能驱动的测试生成器可以通过分析 UI 层次结构自动创建 POM 类,在保持逻辑关注点分离的同时,加快端到端测试的创建速度。

POM 促进模块化和可重用的测试组件,从而能够与基于 AI 的测试维护工具集成,这些工具可以自动更新定位器,减少脚本的脆弱性和维护开销。

总结一下这篇文章: