我们上一篇文章使用Selenium的参数化注解构建多个测试套件,配合TestNG可以在命令行或者终端运行测试命令,今天的文章我们利用PageObjects来抽象你的页面对象,通过Page Objects、Page Sections、Page Element、PageFactory、PageFilters和Dependency Injection来抽象页面元素并结合Selenium自动化你的项目,接下来我为大家分享一下我的学习经验,希望对大家有所帮助。
开发环境
- Window 10.0.17763
- Java 8.0.191
- Chrome 73.0.3683
- IDEA 2018.3
Maven Version
Build Version
4.0.0
org.springframework.boot
spring-boot-starter-parent
2.1.7.RELEASE
me.weitao.app
selenium-pom-tour
0.0.1-SNAPSHOT
selenium-pom-tour
A Selenium POM Tour for Spring Boot
UTF-8
UTF-8
1.8
AliYun Repository
AliYun Repository
http://maven.aliyun.com/nexus/content/groups/public
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-devtools
runtime
true
org.projectlombok
lombok
true
org.testng
testng
6.14.3
test
com.aventstack
extentreports
4.0.9
com.aventstack
extentreports-testng-adapter
1.0.3
uk.sponte.automation
selenium-pom
3.0.14
test
org.springframework.boot
spring-boot-starter-test
test
org.springframework.boot
spring-boot-maven-plugin
org.apache.maven.plugins
maven-surefire-plugin
${basedir}/src/test/resources/testng.xml
什么是POM
POM是页面对象模型(Page Object Model)的简称,也是Selenium框架内置实现页面的抽象,我们可以利用它枚举、操作、查找页面的元素,通过驱动的方式来执行页面的行为。
原理解读
构建步骤
我们的示例项目以Spring Boot为基准项目来演示POM的使用
添加依赖
参考
构建基础Page对象
为了统一处理页面驱动和驱动等待等属性,我们声明了driver
和wait
两个属性来存储,并声明构造方法和一些元素操作的方法,下面给出该文件的示例代码,仅供大家参考。
package me.weitao.app.pages;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.testng.Assert;
/**
* @author Watony Weng
*/
public class BasePage {
public WebDriver driver;
public WebDriverWait wait;
public BasePage(WebDriver driver) {
this.driver = driver;
wait = new WebDriverWait(driver, 15);
}
public void waitVisibility(By elementBy) {
wait.until(ExpectedConditions.visibilityOfAllElementsLocatedBy(elementBy));
}
public void click(By elementBy) {
waitVisibility(elementBy);
driver.findElement(elementBy).click();
}
public void writeText(By elementBy, String text) {
waitVisibility(elementBy);
driver.findElement(elementBy).sendKeys(text);
}
public String readText(By elementBy) {
waitVisibility(elementBy);
return driver.findElement(elementBy).getText();
}
public void assertEquals(By elementBy, String expectedText) {
waitVisibility(elementBy);
Assert.assertEquals(readText(elementBy), expectedText);
}
}
创建百度搜索实现类
假设我们想通过搜索关键字的方式打开百度首页,并输入搜索关键字Selenium PageObjects with Java
,然后点击搜索结果页的链接并跳转到我们的博客园参考页面,最后通过Assert.assertEquals
验证页面的标题,下面给出该文件的示例代码,仅供大家参考。
package me.weitao.app.pages;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testng.Assert;
/**
* @author Watony Weng
*/
public class HomePage extends BasePage {
private static final Logger LOG = LoggerFactory
.getLogger(HomePage.class);
private static final String BASE_URL = "http://www.baidu.com/";
public HomePage(WebDriver driver) {
super(driver);
}
/**
* 页面搜索
*
* @param keyword 搜索关键字
*/
public void testSearch(String keyword) {
driver.get(BASE_URL);
writeText(By.id("kw"), keyword);
click(By.id("su"));
LOG.info("after search url is :{}", driver.getCurrentUrl());
}
/**
* 链接跳转
*/
public void testClick() {
driver.get(BASE_URL + "s?ie=utf-8&f=8&rsv_bp=1&rsv_idx=1&tn=baidu&wd=Selenium%20PageObjects%20with%20Java&rsv_pq=90d822e0000248fe&rsv_t=14510I%2FJ6J5FZIjaYSQoQZ0hlAO4TG2Oa420IuApxqU%2FaK4dCRj4WZPCWUI&rqlang=cn&rsv_enter=0&rsv_dl=tb&rsv_sug3=30&inputT=347&rsv_sug4=347");
click(By.xpath("//*[@id=\"4\"]/h3/a"));
LOG.info("after click url is :{}", driver.getCurrentUrl());
}
/**
* 标题验证
*/
public void testTitle() {
driver.get("https://www.cnblogs.com/NaCl/p/Selenium.html");
Assert.assertEquals(readText(By.xpath("//*[@id=\"cb_post_title_url\"]")), "Selenium+PageObject+Java实现测试用例");
LOG.info("after title url is :{}", driver.getCurrentUrl());
}
}
创建测试基类
我们编写完页面对象后,接下来需要通过TestNG
的注解来调用我们的Page
对象的方法,比如搜索、点击、跳转等方法,下面给出该文件的示例代码,仅供大家参考。
package me.weitao.app.tests;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import java.util.concurrent.TimeUnit;
/**
* @author Watony Weng
*/
public class BaseTest {
public WebDriver driver;
@BeforeClass
public void setUp() {
System.setProperty("webdriver.chrome.driver", "C:\\Program Files (x86)\\Google\\Chrome\\Application\\chromedriver.exe");
ChromeOptions chromeOptions = new ChromeOptions();
chromeOptions.addArguments("--start-maximized");
driver = new ChromeDriver(chromeOptions);
driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
}
@AfterClass
public void tearDown() {
driver.quit();
}
}
创建测试类
我们实现基类并获取driver
属性,然后定义测试方法来测试Page对象,下面给出该文件的示例代码,仅供大家参考。
package me.weitao.app.tests;
import com.aventstack.extentreports.testng.listener.ExtentITestListenerClassAdapter;
import me.weitao.app.pages.HomePage;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Listeners;
import org.testng.annotations.Test;
/**
* @author Watony Weng
*/
@Listeners({ExtentITestListenerClassAdapter.class})
public class HomeTest extends BaseTest {
private HomePage homePage;
@BeforeMethod
public void before() {
homePage = new HomePage(driver);
}
@Test(priority = 1)
public void testHomeSearch() {
homePage.testSearch("Selenium PageObjects with Java");
}
@Test(priority = 2)
public void testHomeClick() {
homePage.testClick();
}
@Test(priority = 3)
public void testHomeTitle() {
homePage.testTitle();
}
@AfterMethod
public void after() {
homePage = null;
}
}
配置Test文件
完成以上的步骤后,我们可以在testng.xml
文件中配置测试套件并配置可以启动的测试类,下面给出该文件的示例代码,仅供大家参考。
配置测试报告选项
我们在pom文件中配置了extentreports
,可以生成测试报告,配合maven-surefire-plugin
查看可以生成不同的测试报告,这里给出extent.properties
和html-config.xml
配置文件的内容如下:
extent.reporter.avent.start=false
extent.reporter.bdd.start=false
extent.reporter.cards.start=false
extent.reporter.email.start=false
extent.reporter.html.start=true
extent.reporter.klov.start=false
extent.reporter.logger.start=false
extent.reporter.tabular.start=false
extent.reporter.avent.config=
extent.reporter.bdd.config=
extent.reporter.cards.config=
extent.reporter.email.config=
extent.reporter.html.config=src/test/resources/html-config.xml
extent.reporter.klov.config=
extent.reporter.logger.config=
extent.reporter.tabular.config=
extent.reporter.avent.out=target/extent-reports/AventReport/
extent.reporter.bdd.out=target/extent-reports/BddReport/
extent.reporter.cards.out=target/extent-reports/CardsReport/
extent.reporter.email.out=target/extent-reports/EmailReport/ExtentEmail.html
extent.reporter.html.out=target/extent-reports/HtmlReport/ExtentHtml.html
extent.reporter.logger.out=target/extent-reports/LoggerReport/
extent.reporter.tabular.out=target/extent-reports/TabularReport/
standard
UTF-8
true
https
Extent and TestNG Integration
Extent Report
true
运行测试命令
我们最后在Idea
的Terminal窗口执行以下命令,即可看到测试用例的运行结果。
npm clean test
查看测试报告
我们在
target/extent-reports/HtmlReport
目录下即可看到生成的测试报告。
参考
- Page Objects
个人感想与收获
通过以上知识点的学习,我们知道了如何通过Page对象抽象我们的业务页面,然后借助Driver来控制浏览器,最后完成页面元素的一系列操作,我们自此完成了基本的自动化操作,再配合DataProvider更能把页面元素抽象化和实例化,让我们能更加从容地使用Selenium,借助这个工具完成能更方便地服务于我们的业务逻辑,接下来我们会继续探索Selenium这个框架,从其他方面优化、抽象、提升我们的测试水平,提升软件质量,服务更多的用户。希望大家保持学习的热情,继续充实自己的技能包,打造更高要求的研发团队,向更高更快的方向进发。