Selenium 简明教程
Selenium WebDriver - Page Factory
使用 Selenium Webdriver 开发的测试用例可以通过在测试中结合不同的设计模式来简化。其中一种广泛使用 的设计模式是页面对象模型,俗称 POM。为了实现页面对象模型,我们可以借助于被称为页面工厂的工厂类。页面工厂类来自 Selenium Webdriver。
What is a Page Factory?
如前所述,页面工厂是一个帮助实现页面对象模型的类。它是页面对象模型的改进版本,由 Webdriver 类提供。它具有使用注释来初始化构成页面对象的 web 元素的功能。
Features of Page Factory
@FindBy
此注释用于页面工厂中,借助于各种定位器(如 id、名称、类名称、链接文本、部分链接文本、css、xpath 和标签名)来标识、声明和对 web 元素执行操作。
FindBy(name = "elementname")
WebElement e;
@FindBys
这个注释用在 Page Factory 中,用于识别、声明并对 web 元素执行操作,通过使用 ID、名称、类名称、链接文本、部分链接文本、CSS、Xpath 和 Tagname 这些各种定位器,通过指定多重搜索条件来识别。搜索条件中的 ADD 条件必须满足,才能唯一识别一个元素。
@FindBys({
@FindBy(tagname = "a"),
@FindBy(linkText = "Search")
})
WebElement lnk;
在上面的示例中,如果满足所有这两个条件,我们将能够识别 Web 元素。
@FindAll
PageFactory 中的此注解类似于 @FindBys,因为它允许使用多个搜索条件。但是,为了唯一找到一个元素,需要满足任何一个条件(条件之间的或条件应为真)。
@FindAll({
@FindBy(tagname = "a"),
@FindBy(linkText = "Search"),
@FindBy(class = "name"),
})
WebElement btn;
在上面的示例中,如果满足三个条件中的任何一个,我们将能够识别一个 Web 元素。
Difference between Page Factory and Page Object Model
下面列出了页面工厂和页面对象之间的差异:
-
在页面工厂中,元素通过 @FindBy 标识,而在页面对象模型中,元素使用 By 标识。
-
页面工厂具有页面对象模型中没有的延迟初始化概念。
-
页面对象模型是一种设计模式,而页面工厂是 Webdriver 类中可用于帮助实现页面对象模型的类。
-
在页面对象模型中,必须单独初始化每个对象,而在页面工厂中,initElement() 方法一次初始化所有对象。
Example
在下面的示例中,单击 New User 。
单击 New User 按钮后,我们将转到 Welcome, Register 文本的注册页面。
对于上面的示例,我们将创建两个页面类 - WelcomePage.java 和 RegisterPage.java,我们将在这些各自的页面(使用 @FindBy 注释)上声明网页元素以及对这些元素执行的操作。
我们还将创建测试类 - WelcomePageTest.java,其中将包含实际测试用例、初始化 WelcomePage 和 RegisterPage 的驱动程序对象以及与该测试用例相关的断言。所有测试用例都位于同一 POM 包中。
页面类 WelcomePage.java 上的代码实现。
package POM;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.PageFactory;
public class WelcomePage {
WebDriver driver;
@FindBy(xpath = "//*[@id='signInForm']/h1")
WebElement text;
@FindBy(xpath = "//*[@id='signInForm']/div[3]/a")
WebElement btn;;
public WelcomePage(WebDriver driver) {
this.driver=driver;
// initializing all page objects
PageFactory.initElements(driver, this);
}
public String verifyPageHeading() {
String getHeadtext = text.getText();
return getHeadtext;
}
public void clickOnNewUser() {
btn.click();
}
}
页面类 RegisterPage.java 上的代码实现。
package POM;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.PageFactory;
public class RegisterPage {
WebDriver driver;
@FindBy(xpath = "//*[@id='signupForm']/h1")
WebElement text;
public RegisterPage(WebDriver driver) {
this.driver=driver;
// initializing all page objects
PageFactory.initElements(driver, this);
}
public String verifyPageHeading() {
String getHeadtext = text.getText();
return getHeadtext;
}
}
测试类 WelcomePageTest.java 上的代码实现。
package POM;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.testng.annotations.*;
import java.util.concurrent.TimeUnit;
import static org.testng.Assert.assertEquals;
public class WelcomePageTest {
WebDriver driver;
WelcomePage objWelcomePage;
RegisterPage objRegisterPage;
@BeforeTest
public void setup() {
// Initiate the Webdriver
driver = new ChromeDriver();
// adding implicit wait of 12 secs
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
// Opening the webpage
driver.get("https://www.tutorialspoint.com/selenium/practice/login.php");
}
@Test(priority = 1)
public void verifyWelcomePageHeading() {
// object of WelcomePage page class
objWelcomePage = new WelcomePage(driver);
String text = objWelcomePage.verifyPageHeading();
System.out.println("Page heading in Welcome Page: " + text);
// assertions to test case
assertEquals("Welcome, Login In", text);
}
@Test(priority = 2)
public void moveToRegisterPage() {
objWelcomePage = new WelcomePage(driver);
objWelcomePage.clickOnNewUser();
}
@Test(priority = 3)
public void verifyRegisterPageHeading() {
// object of RegisterPage page class
objRegisterPage = new RegisterPage(driver);
String text = objRegisterPage.verifyPageHeading();
System.out.println("Page heading in Register Page: " + text);
// assertions to test case
assertEquals("Welcome,Register", text);
}
@AfterTest
public void teardown() {
// quitting browser
driver.quit();
}
}
pom.xml 中的依赖项。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>SeleniumJava</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>16</maven.compiler.source>
<maven.compiler.target>16</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<!-- https://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-java -->
<dependencies>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>4.11.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.testng/testng -->
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>7.9.0</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
Page heading in Welcome Page: Welcome, Login In
Page heading in Register Page: Welcome,Register
===============================================
Default Suite
Total tests run: 3, Passes: 3, Failures: 0, Skips: 0
===============================================
在上面的示例中,我们首先定位了 Welcome 和 Register 页面上的元素,并在页面类 WelcomePage.java 和 RegisterPage.java 中对这些元素执行了操作。
在测试类 WelcomePageTest.java 中,我们声明了这些页面类的对象以设计测试用例的整个流程。
上面的实现中使用了 TestNG 测试框架和页面工厂。我们在控制台获得了带有消息的页面标题 - Page heading in Welcome Page: Welcome, Login In 和 Page heading in Register Page: Welcome,Register 。
控制台中的结果有 Total tests run: 3 ,因为有三个方法:
-
verifyWelcomePageHeading()
-
moveToRegisterPage()
-
verifyRegisterPageHeading()
最后,收到消息 Passes: 3 和 Process finished with exit code 0 ,表示代码已成功执行。