页面对象模型和工厂 Selenium
⚡ 智能摘要
页面对象模型和页面工厂 Selenium 定义一种结构化的设计模式,用于构建健壮、易维护的测试自动化框架。它强调创建页面特定的类来封装 Web 元素及其行为,从而减少重复代码,提高代码的可读性和可扩展性。 Selenium 测试脚本。
什么是页面对象模型?它的关键组成部分是什么?
页面对象模型 (POM) 是一种设计模式,常用于测试自动化,它为 Web UI 元素创建对象库。该模型的优势在于减少了代码重复并提高了测试维护的便捷性。
在此模型下,应用程序中的每个网页都应该有一个对应的页面类。该页面类将标识该网页的 Web 元素,并包含对这些 Web 元素执行操作的页面方法。这些方法的名称应与其执行的任务相符,例如,如果加载器正在等待支付网关出现,则 POM 方法名称可以命名为 waitForPaymentScreenDisplay()。
页面对象模型的关键组成部分
- 页面类别: 将每个网页表示为一个单独的类。
- 定位器: 使用 ID、XPath 或 CSS 选择器识别网页元素。
- 方法: 包含对 .page 元素执行的操作或操作。
- 可重用性: Promo测试代码可重用,且更易于跨测试进行维护。
- 关注点分离: 为了更好地组织页面结构,使页面结构与测试逻辑保持独立。
为什么选择页面对象模型?
在 UI 自动化中启动 Selenium 网络驱动程序 这并不是一项艰巨的任务。你只需要找到元素并对它们进行操作即可。
请看这个简单的网站登录脚本。
正如您所看到的,我们所做的就是查找元素并为这些元素填充值。
这是一个耗时且容易出错的脚本。起初看似简单,但随着测试套件的扩展,管理元素变更就会变得困难。而且随着时间的推移,测试套件还会不断增长。随着代码行数的不断增加,事情会变得越来越棘手。
脚本维护的主要问题是,如果 10 个不同的脚本使用同一个页面元素,那么一旦该元素发生任何变化,您就需要更改所有 10 个脚本。这非常耗时,而且容易出错。
更好的脚本维护方法是创建一个单独的类文件,用于查找网页元素、填充元素或验证元素。这样,多个与同一元素交互的测试脚本就可以重复使用这个类。将来,如果网页元素发生更改,我们只需要修改一个类文件,而无需修改十个不同的脚本。
这种方法在 Selenium它有助于提高代码的可读性、可维护性和可重用性。
👉 免费报名参加直播 Selenium 项目
POM的优点
- 页面对象设计模式认为 UI 中的操作和流程应该与验证分开。这个概念使我们的代码更简洁、更易于理解。
- 第二个好处是对象库独立于测试用例,因此我们可以使用同一个对象库和不同的工具来实现不同的目的。例如,我们可以将页面对象模型集成到…… Selenium - TestNG/JUnit 功能性 测试与验证 同时与 JBehave/Cucumber 进行验收测试。
- Code 由于它重用了 POM 类中的页面方法,因此变得更简洁、更优化。
- 方法名称更加贴近实际,更容易与用户界面中发生的操作相对应。例如,如果点击按钮后跳转到首页,则方法名称将类似于“gotoHomePage()”。
如何在POM中实现 Selenium?
页面对象模型框架基础结构中的简单 PLog,其中 whereManagereIDElements 的 AUT 操作这些 Web 元素的方法保存在一个 clog 文件中。验证之类的任务应该作为测试方法的一部分单独列出。
完整示例
测试用例: 在MyCAD中点击 软件更新 Guru99 演示站点。
步骤1)前往 Guru99 演示网站
步骤 2)在首页上,检查文本“Guru99银行”在场
步骤 3)登录应用程序
步骤 4)验证主页是否包含文本“Manger Id: demo”
在这个例子中,我们要处理两个页面:
- 登录页面
- 主页(登录后显示)
因此,我们在 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 元素。
@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"));
}
}
完整的项目结构如下图所示:
AjaxElementLocatorFactory
AjaxElementLocatorFactory 是 PageFactory 中的延迟加载概念 Selenium它用于仅在元素用于任何操作时才查找 Web 元素。它为 WebElements 对象页面类设置超时时间。使用 PageFactory 模式的主要优势之一是…… Selenium 是 AjaxElementLocatorFactory 类。
这里,当对某个元素执行操作时,等待其可见性的计时才从那一刻开始。如果在给定的时间间隔内未找到该元素, 测试用例 执行会抛出‘NoSuchElementException’异常。
例如:
AjaxElementLocatorFactory factory = new AjaxElementLocatorFactory(driver, 10); PageFactory.initElements(factory, this);












