• Selenium Video Tutorials

Selenium WebDriver - 页面工厂



使用 Selenium Webdriver 开发的测试用例可以通过在测试中整合不同的设计模式来简化。其中一个广泛使用设计模式是页面对象模型,通常称为 POM。为了实现页面对象模型,我们可以借助工厂类,也就是页面工厂。页面工厂类可从 Selenium Webdriver 获得。

什么是页面工厂?

如前所述,页面工厂是一个有助于实现页面对象模型的类。它是页面对象模型的改进版本,由 Webdriver 类提供。它具有使用注解初始化构成页面对象的 Web 元素的功能。

页面工厂的特性

@FindBy

此注解在页面工厂中用于识别、声明和执行 Web 元素的操作,借助各种定位器,如 id、name、class name、link text、partial link text、css、xpath 和 tagname。

语法

FindBy(name = "elementname") 
WebElement e;

@FindBys

此注解在页面工厂中用于识别、声明和执行 Web 元素的操作,借助各种定位器,如 id、name、class name、link text、partial link text、css、xpath 和 tagname,通过指定多个搜索条件。必须满足搜索条件之间的 AND 条件才能唯一识别元素。

语法

@FindBys({
   @FindBy(tagname = "a"),
   @FindBy(linkText = "Search")
})
WebElement lnk;

在上面的示例中,如果满足所有两个条件,我们将能够识别一个 Web 元素。

@FindAll

页面工厂中的此注解类似于 @FindBys,因为它允许多个搜索条件。但是,为了唯一地定位元素,需要满足任何一个条件(条件之间的 OR 条件必须为真)。

语法

@FindAll({
   @FindBy(tagname = "a"),
   @FindBy(linkText = "Search"),
   @FindBy(class = "name"),
})
WebElement btn;

在上面的示例中,如果满足三个条件中的任何一个,我们将能够识别一个 Web 元素。

@CacheLookUp

此注解在页面工厂中用于优化执行速度。这通常用于引用测试中经常使用的元素,例如每次每个测试用例都需要使用的用户凭据。它允许在第一次使用后将常用变量存储在缓存内存中。此注解可以与其他页面工厂注解同时使用。

语法

@CacheLookUp
@FindAll({
   @FindBy(tagname = "a"),
   @FindBy(linkText = "Search"),
   @FindBy(class = "name"),
})
WebElement loginBtn;

initElement()

它是页面工厂类中的一个静态方法,用于初始化由 @FindBy 注解识别的所有 Web 元素。

延迟初始化

AjaxElementLocatorFactory 基于页面工厂中的延迟加载思想来定位操作中的 Web 元素并传递超时时间。这通常用于具有 Ajax 元素的应用程序。

页面工厂和页面对象模型的区别

页面工厂和页面对象之间的区别如下所示:

  • 在页面工厂中,元素由 @FindBy 识别,而在页面对象模型中,元素使用 By 识别。
  • 页面工厂具有页面对象模型中不存在的延迟初始化的概念。
  • 页面对象模型是一种设计模式,而页面工厂是 Webdriver 类中可用的一个类,它有助于实现页面对象模型。
  • 在页面对象模型中,每个对象都必须单独初始化,而在页面工厂中,initElement() 方法一次初始化所有对象。

示例

在下面的示例中,单击“新用户”。

Selenium Page Factory 1

单击“新用户”按钮后,我们将转到注册页面,显示“欢迎,注册”文本。

Selenium Page Factory 2

对于以上示例,我们将创建两个页面类 - WelcomePage.java 和 RegisterPage.java,其中我们将分别在这些页面上声明 Web 元素(使用 @FindBy 注解)以及要对这些元素执行的操作。

我们还将创建测试类 - WelcomePageTest.java,其中将包含实际的测试用例、初始化 WelcomePage 和 RegisterPage 的驱动程序对象以及与该测试用例相关的断言。所有测试用例都将在同一个 POM 包下。

Selenium Page Factory 3

页面类 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://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
===============================================
Selenium Page Factory 4

在上面的示例中,我们首先在 Welcome 和 Register 页面上定位了元素,并在页面类 WelcomePage.java 和 RegisterPage.java 中对它们执行了操作。

在测试类 WelcomePageTest.java 中,我们声明了这些页面类的对象以设计测试用例的整个流程。

上述实现中使用了 TestNG 测试框架以及页面工厂。我们在控制台中获得了带有消息的页面标题 - “欢迎页面标题:欢迎,登录”和“注册页面标题:欢迎,注册”。

控制台中的结果显示“已运行的测试总数:3”,因为有三个方法:

  • verifyWelcomePageHeading()
  • moveToRegisterPage()
  • verifyRegisterPageHeading()

最后,收到消息“通过:3”和“进程已完成,退出代码为 0”,表示代码已成功执行。

结论

本教程全面介绍了 Selenium WebDriver 页面工厂。我们从页面工厂的描述开始,逐步讲解了页面工厂的功能、页面对象模型和页面工厂之间的区别,并通过一个示例说明了如何将页面工厂与 Selenium 结合使用。这将使您深入了解页面工厂。建议您持续练习所学内容,并探索与 Selenium 相关的其他知识,以加深理解并拓宽视野。

广告