Selenium 简明教程
Selenium WebDriver - Page Factory
使用 Selenium Webdriver 开发的测试用例可以通过在测试中结合不同的设计模式来简化。其中一种广泛使用 的设计模式是页面对象模型,俗称 POM。为了实现页面对象模型,我们可以借助于被称为页面工厂的工厂类。页面工厂类来自 Selenium Webdriver。
The test cases developed using Selenium Webdriver can be streamlined by incorporating different design patterns within the tests. One of the widely used design patterns is Page Object Model, popularly known as the POM. In order to implement a Page Object Model, we can take help of the factory class which is known as the Page Factory. The Page Factory class is available from the Selenium Webdriver.
What is a Page Factory?
如前所述,页面工厂是一个帮助实现页面对象模型的类。它是页面对象模型的改进版本,由 Webdriver 类提供。它具有使用注释来初始化构成页面对象的 web 元素的功能。
As mentioned previously, a Page Factory is a class which aids in implementing a Page Object Model. It is an improved version of Page Object Model and it is provided by the Webdriver class. It has the feature to use annotations to initialize the web elements which constitute the page objects.
Features of Page Factory
@FindBy
此注释用于页面工厂中,借助于各种定位器(如 id、名称、类名称、链接文本、部分链接文本、css、xpath 和标签名)来标识、声明和对 web 元素执行操作。
This annotation is used in Page Factory to identify, declare, and perform actions on the web elements with the help of various locators like id, name, class name, link text, partial link text, css, xpath, and tagname.
FindBy(name = "elementname")
WebElement e;
@FindBys
这个注释用在 Page Factory 中,用于识别、声明并对 web 元素执行操作,通过使用 ID、名称、类名称、链接文本、部分链接文本、CSS、Xpath 和 Tagname 这些各种定位器,通过指定多重搜索条件来识别。搜索条件中的 ADD 条件必须满足,才能唯一识别一个元素。
This annotation is used in Page Factory to identify, declare, and perform actions on the web elements with the help of various locators like id, name, class name, link text, partial link text, css, xpath, and, tagname by specifying multiple search conditions. An ADD condition among search criterias has to be met to identify an element uniquely.
@FindBys({
@FindBy(tagname = "a"),
@FindBy(linkText = "Search")
})
WebElement lnk;
在上面的示例中,如果满足所有这两个条件,我们将能够识别 Web 元素。
In the above example, if all the two conditions are met, we will be able to identify a web element.
@FindAll
PageFactory 中的此注解类似于 @FindBys,因为它允许使用多个搜索条件。但是,为了唯一找到一个元素,需要满足任何一个条件(条件之间的或条件应为真)。
This annotation in Page Factory is similar to @FindBys since it allows multiple search conditions. However, in order to locate an element uniquely, any one condition needs to be satisfied(OR condition among the criterias should be true).
@FindAll({
@FindBy(tagname = "a"),
@FindBy(linkText = "Search"),
@FindBy(class = "name"),
})
WebElement btn;
在上面的示例中,如果满足三个条件中的任何一个,我们将能够识别一个 Web 元素。
In the above example, if anyone of the three conditions are met, we will be able to identify a web element.
@CacheLookUp
此注解用于 PageFactory 来优化执行速度。这通常用于引用测试中经常使用的元素,例如用户凭据,这对于每个测试用例都是必需的。它允许在首次使用后将经常使用的变量储存在缓存内存中。此注解可以与其他 PageFactory 注解同时使用。
This annotation is used in Page Factory to optimize the execution speed. This is usually used to refer to an element used frequently in a test, for example the user credentials which will be required every time for every test case. It allows to stock up the frequently used variables in the cache memory post the first time usage. This annotation can be used simultaneously along with other Page Factory annotations.
@CacheLookUp
@FindAll({
@FindBy(tagname = "a"),
@FindBy(linkText = "Search"),
@FindBy(class = "name"),
})
WebElement loginBtn;
Difference between Page Factory and Page Object Model
下面列出了页面工厂和页面对象之间的差异:
The differences between the Page Factory and Page Object are listed below −
-
In Page Factory, the elements are identified by @FindBy, where in Page Object Model, the elements are identified using the By.
-
Page Factory has the concept of lazy initialization which is absent in Page Object Model.
-
Page Object Model is a design pattern while the Page Factory is a class available in the Webdriver class which helps to implement the Page Object Model.
-
In Page Object Model, every object has to be initialized separately, while in the Page Factory, the initElement() method initializes all objects at once.
Example
在下面的示例中,单击 New User 。
In the below example, click on New User.
单击 New User 按钮后,我们将转到 Welcome, Register 文本的注册页面。
On clicking on the New User button, we will go to the Registration page, with the Welcome, Register text.
对于上面的示例,我们将创建两个页面类 - WelcomePage.java 和 RegisterPage.java,我们将在这些各自的页面(使用 @FindBy 注释)上声明网页元素以及对这些元素执行的操作。
For the above example, we will create two page classes - WelcomePage.java and RegisterPage.java where we would have the web elements declared on these respective pages(using the @FindBy annotation) and actions to be performed on those elements.
我们还将创建测试类 - WelcomePageTest.java,其中将包含实际测试用例、初始化 WelcomePage 和 RegisterPage 的驱动程序对象以及与该测试用例相关的断言。所有测试用例都位于同一 POM 包中。
We would also create the test class - WelcomePageTest.java which would contain the actual test case, initialize the driver objects of the WelcomePage and RegisterPage, and assertions related to that test case. All the test cases would be under the same POM package.
页面类 WelcomePage.java 上的代码实现。
Code Implementation on page class 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 上的代码实现。
Code Implementation on page class 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 上的代码实现。
Code Implementation on test class 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 中的依赖项。
Dependencies in 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 中对这些元素执行了操作。
In the above example, we had first located the elements on the Welcome and Register pages and performed actions on them inside the page classes - WelcomePage.java and RegisterPage.java.
在测试类 WelcomePageTest.java 中,我们声明了这些页面类的对象以设计测试用例的整个流程。
Inside the test class WelcomePageTest.java, we had declared objects of those page classes to design the whole flow of the test case.
上面的实现中使用了 TestNG 测试框架和页面工厂。我们在控制台获得了带有消息的页面标题 - Page heading in Welcome Page: Welcome, Login In 和 Page heading in Register Page: Welcome,Register 。
TestNG test framework along with Page Factory is used in the above implementation. We had obtained the page headers with the messages in the console - Page heading in Welcome Page: Welcome, Login In and Page heading in Register Page: Welcome,Register.
控制台中的结果有 Total tests run: 3 ,因为有三个方法:
The result in the console has Total tests run: 3, as there are three methods −
-
verifyWelcomePageHeading()
-
moveToRegisterPage()
-
verifyRegisterPageHeading()
最后,收到消息 Passes: 3 和 Process finished with exit code 0 ,表示代码已成功执行。
At last, the message Passes: 3, and Process finished with exit code 0 was received, depicting successful execution of the code.
Conclusion
以下是对 Selenium WebDriver 页面工厂教程的全面解析。我们从描述页面工厂开始,然后逐步讲解了页面工厂的功能、页面对象模型与页面工厂之间的差异,以及介绍如何结合 Selenium 使用页面工厂的一个示例。这将让你深入了解页面工厂。明智的做法是对学过的内容反复练习,探索其他与 Selenium 相关的知识,以加深理解并拓展视野。
This concludes our comprehensive take on the tutorial on Selenium Webdriver Page Factory. We’ve started with describing a Page Factory, and walked through the features of a Page Factory, differences between Page Object Model and Page Factory, and an example illustrating how to use Page Factory along with Selenium. This equips you with in-depth knowledge of the Page Factory. It is wise to keep practicing what you’ve learned and exploring others relevant to Selenium to deepen your understanding and expand your horizons.