Java语言UI自动化框架学习总结
跟着CSDN的一位前辈搭建了基于Java语言的Web自动化框架,总结一下自己所学
整体架构基于Selenium和TestNG,用到了一些第三方库用来锦上添花,如:
log4j 日志输出
allure 美化测试报告
commons-io 截图支持
前辈主页(https://blog.csdn.net/Keep_Learn2020?type=blog)
不要等改了一大堆才运行程序!
不要等改了一大堆才运行程序!
不要等改了一大堆才运行程序!
<dependencies>
<!-- https://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-java -->
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>4.1.1</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<!-- https://mvnrepository.com/artifact/io.qameta.allure/allure-testng -->
<dependency>
<groupId>io.qameta.allure</groupId>
<artifactId>allure-testng</artifactId>
<version>2.17.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.11.0</version>
</dependency>
</dependencies>
1.封装浏览器工具类
1.1 导入selenium依赖
<!--selenium依赖,必备-->
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>4.1.1</version>
</dependency>
1.2 新建utils包,在包下新建WebDriverUtils工具类
因为我只用chrome浏览器,所以只写了这个,大佬有写别的浏览器,有需要的可以去看
package utils;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
public class WebDriverUtils {
public static WebDriver webDriver;
public static void openBrowser(String browserName){
if ("chrome".equals(browserName)){
System.setProperty("webdriver.chrome.driver","D:\\Python\\chromedriver.exe");
webDriver = new ChromeDriver();
}
}
}
2. 实现登录功能
新建包结构:testcase包,用来保存测试用例
新建一个TestCaseLogin类,线性代码实现单个登录功能,为了方便调试,加入try catch 代码块且每个动作都加了延迟
package testcase;
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 utils.WebDriverUtils;
public class TestCaseLogin {
public static void main(String[] args) throws InterruptedException {
WebDriverUtils.openBrowser("chrome");
WebDriver webDriver = WebDriverUtils.webDriver;
webDriver.get("测试地址");
webDriver.findElement(By.xpath("xpath")).sendKeys("username");
Thread.sleep(1000);
webDriver.findElement(By.xpath("xpath")).sendKeys("password");
Thread.sleep(1000);
webDriver.findElement(By.className("login-btn")).click();
Thread.sleep(3000);
//显示等待应用
WebDriverWait wait = new WebDriverWait(webDriver, 5);
try {
wait.until(ExpectedConditions.visibilityOfElementLocated(By.className("layout-logo-sys")));
System.out.println("测试通过!");
} catch (Exception e) {
System.out.println("测试不通过!");
}finally {
webDriver.quit();
}
}
}
3. TestNG
3.1 导入testng
<!--testng依赖,必备-->
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>7.5</version>
<scope>test</scope>
</dependency>
3.2 加入TestNG注解
使用testng注解,修改TestCaseLogin类中的线性代码
package testcase;
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;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import utils.WebDriverUtils;
public class TestCaseLogin {
public WebDriver webDriver;
@BeforeMethod
public void setupMethod() {
WebDriverUtils.openBrowser("chrome");
webDriver = WebDriverUtils.webDriver;
webDriver.get("测试网址");
webDriver.manage().window().maximize();
}
@Test
public void testCaseLogin() throws InterruptedException {
webDriver.findElement(By.xpath("xpath")).sendKeys("username");
Thread.sleep(1000);
webDriver.findElement(By.xpath("xpath")).sendKeys("password");
Thread.sleep(1000);
webDriver.findElement(By.className("login-btn")).click();
Thread.sleep(3000);
//显示等待应用
WebDriverWait wait = new WebDriverWait(webDriver, 5);
try {
wait.until(ExpectedConditions.visibilityOfElementLocated(By.className("layout-logo-sys")));
Assert.assertTrue(true);
} catch (Exception e) {
Assert.fail();
}
}
@AfterMethod
public void teardownMethod() {
webDriver.quit();
}
}
4. PO设计
4.1 封装属性和行为
新建一个page包,编写一个LoginPage类,把元素属性和行为封装起来
package page;
import org.openqa.selenium.By;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import utils.WebDriverUtils;
public class LoginPage {
/*
不需要一次性把所有属性都写完,可以一边用一边写
属性:元素信息(定位方式+定位值)
*/
By userNameBy = By.xpath("//*[@type='text']");
By passWordBy = By.xpath("//*[@type='password']");
By loginBtnBy = By.className("login-btn");
//行为-->操作
//输入用户名
public void inputUserName(String userName) {
WebDriverWait wait = new WebDriverWait(WebDriverUtils.webDriver, 5);
wait.until(ExpectedConditions.visibilityOfElementLocated(userNameBy)).sendKeys(userName);
}
//输入密码
public void inputPassWord(String passWord) {
WebDriverWait wait = new WebDriverWait(WebDriverUtils.webDriver, 5);
wait.until(ExpectedConditions.visibilityOfElementLocated(passWordBy)).sendKeys(passWord);
}
//点击登录按钮
public void clickLoginBtn() {
WebDriverWait wait = new WebDriverWait(WebDriverUtils.webDriver, 5);
wait.until(ExpectedConditions.elementToBeClickable(loginBtnBy)).click();
}
}
4.2 修改登录流程
把线性代码修改为PO写法
package testcase;
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;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import page.LoginPage;
import utils.WebDriverUtils;
public class TestCaseLogin {
public WebDriver webDriver;
@BeforeMethod
public void setupMethod() {
//前置动作
WebDriverUtils.openBrowser("chrome");
webDriver = WebDriverUtils.webDriver;
webDriver.get("测试地址");
webDriver.manage().window().maximize();
}
@Test
public void testCaseLoginSuccess() throws InterruptedException {
//登录流程
LoginPage loginPage = new LoginPage();
loginPage.inputUserName("username");
loginPage.inputPassWord("password");
loginPage.clickLoginBtn();
//显示等待应用
WebDriverWait wait = new WebDriverWait(webDriver, 5);
try {
wait.until(ExpectedConditions.visibilityOfElementLocated(By.className("layout-logo-sys")));
Assert.assertTrue(true);
} catch (Exception e) {
Assert.fail();
}
}
@AfterMethod
public void teardownMethod() {
//后置动作
webDriver.quit();
}
}
4.3 二次封装
在page包中新建一个BasePage类,把页面共性(元素等待、输入、点击)二次封装
package page;
import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import utils.WebDriverUtils;
import java.time.Duration;
public class BasePage {
//等待元素可见
public WebElement waitElementVisible(By by){
WebDriverWait wait = new WebDriverWait(WebDriverUtils.webDriver, Duration.ofSeconds(5));
return wait.until(ExpectedConditions.visibilityOfElementLocated(by));
}
//等待元素可点击
public WebElement waitElementClickable(By by){
WebDriverWait wait = new WebDriverWait(WebDriverUtils.webDriver, Duration.ofSeconds(5));
return wait.until(ExpectedConditions.elementToBeClickable(by));
}
//输入
public void inputContent(By by,String content){
waitElementVisible(by).sendKeys(content);
}
//点击
public void click(By by){
waitElementClickable(by);
}
}
4.4 修改LoginPage类
简化代码(瞬间舒服了)
package page;
import org.openqa.selenium.By;
public class LoginPage extends BasePage {
/*
不需要一次性把所有属性都写完,可以一边用一边写
属性:元素信息(定位方式+定位值)
*/
By userNameBy = By.xpath("//*[@type='text']");
By passWordBy = By.xpath("//*[@type='password']");
By loginBtnBy = By.className("login-btn");
//行为-->操作
//输入用户名
public void inputUserName(String userName) {
input(userNameBy, userName);
}
//输入密码
public void inputPassWord(String passWord) {
input(passWordBy, passWord);
}
//点击登录按钮
public void clickLoginBtn() {
click(loginBtnBy);
}
}
5. 数据分离
新建一个testdata包,专门保存测试数据相关的类
5.1 创建常量类
- 包里新建Constant类,用于保存类似测试地址之类的常量数据
package testdata;
public class Constant {
//常量一般大写
public static final String LOGIN_URL="测试地址";
}
-
替换TestCase类中的引用地址
webDriver.get(Constant.LOGIN_URL);
5.2 注入参数
5.2.1 创建一个名称为testng.xml文件,填写配置信息
-------------------------------------------------------从这里开始,以后要在testng.xml文件这里运行程序了!!!-----------------------------------------------------------------
右键xml文件,运行程序
<?xml version="1.0" encoding="UTF-8"?>
<suite name="Suite" parallel="false">
<test name="Test">
<!-- 统一配置浏览器类型 -->
<parameter name="browserName" value="chrome"></parameter>
<classes>
<class name="testcase.TestCaseLogin"/>
</classes>
</test> <!-- Test -->
</suite> <!-- Suite -->
5.2.2 前置方法注入浏览器名称参数
@Parameters("browserName")
@BeforeMethod
public void setupMethod(String browserName) {
//前置动作
WebDriverUtils.openBrowser(browserName);
webDriver = WebDriverUtils.webDriver;
webDriver.get(Constant.LOGIN_URL);
webDriver.manage().window().maximize();
}
5.2.3 添加数据源
在testdata包中新建一个TestData类,编写登录成功的数据源
package testdata;
import org.testng.annotations.DataProvider;
public class LoginData {
@DataProvider
public static Object[][] loginDataSuccess(){
Object[][] dataArray={{"username1","password1"},{"username2","password2"}};
return dataArray;
}
}
5.2.4 注入测试用例
@Test(dataProviderClass = LoginData.class,dataProvider = "loginDataSuccess")
public void testCaseLoginSuccess(String userName,String password) throws InterruptedException {
//登录流程
LoginPage loginPage = new LoginPage();
loginPage.inputUserName(userName);
loginPage.inputPassWord(password);
loginPage.clickLoginBtn();
//......省略其他代码
更改断言,测试一下是否能运行(这个时候我已经很久没运行了,不过好在问题不大,报错了马上就改掉了)
//显示等待应用
try {
loginPage.waitElementVisible(By.className("layout-logo-sys"));
Assert.assertTrue(true);
} catch (Exception e) {
Assert.fail();
}
5.3 添加失败测试用例
5.3.1 添加元素
在LoginPage类中添加错误元素的属性和方法
//错误提示语元素属性
By errorNoticeBy = By.xpath("//*[@class='ivu-message-error']/span");
//获取错误提示信息
public String getErrorNotice(){
return waitElementVisible(errorNoticeBy).getText();
}
5.3.2 添加数据
在LoginData类中添加登录失败错误数据
@DataProvider
public static Object[][] loginDataFail(){
Object[][] dataArray={{"username1","password1","错误提示1"},{"username2","password2","错误提示2"}};
return dataArray;
}
5.3.3 添加失败测试用例
在TestCaseLogin中添加失败测试用例
@Test(dataProviderClass = LoginData.class,dataProvider = "loginDataSuccess")
public void testCaseLoginFail(String userName,String passWord,String errorNotice){
//登录流程
LoginPage loginPage = new LoginPage();
loginPage.inputUserName(userName);
loginPage.inputPassWord(passWord);
loginPage.clickLoginBtn();
//断言
String actualNotice=loginPage.getErrorNotice();
Assert.assertEquals(errorNotice,actualNotice);
}
运行一下,解决一下报错
6. 日志集成
6.1 导入maven
<!--日志依赖-->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
6.2 配置信息
在test目录下新建一个resource包,包下新建一个log4j.properties文件,写入以下内容
log4j.rootLogger = INFO,console,file
log4j.appender.console = org.apache.log4j.ConsoleAppender
log4j.appender.console.Target = System.out
log4j.appender.console.layout = org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern = [%p] %d{yyyy-MM-dd HH:mm:ss} method: %l----%m%n
log4j.appender.file = org.apache.log4j.DailyRollingFileAppender
# 日志保存在项目log文件夹下的web_auto.log里,可自定义
log4j.appender.file.File = log/web_auto.log
log4j.appender.file.Append = true
log4j.appender.file.layout = org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern = %d{yyyy-MM-dd HH:mm:ss} method: %l - [ %p ]----%m%n
6.3 日志输出
1.在BasePage中添加日志输出
//实例化日志对象
private Logger logger = Logger.getLogger(BasePage.class);
//省略其他代码......
//输入
public void input(By by, String content){
waitElementVisible(by).sendKeys(content);
logger.info("给【"+by+"】元素输入【"+content+"】内容");
}
2.在WebDriverUtils中添加日志输出
package utils;
import org.apache.log4j.Logger;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
public class WebDriverUtils {
public static WebDriver webDriver;
//因为openBrowser是静态方法,所以日志对象也需要定义成静态的
private static final Logger logger = Logger.getLogger(WebDriverUtils.class);
public static void openBrowser(String browserName){
if ("chrome".equals(browserName)){
System.setProperty("webdriver.chrome.driver","D:\\Python\\chromedriver.exe");
webDriver = new ChromeDriver();
logger.info("打开【chrome】浏览器");
}
}
}
7. 集成Allure
7.1 导入依赖
<!-- allure依赖 -->
<dependency>
<groupId>io.qameta.allure</groupId>
<artifactId>allure-testng</artifactId>
<version>2.17.2</version>
</dependency>
7.2 配置信息
在maven的properties中新增以下信息
<!-- 文件拷贝时的编码 -->
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<!-- 编译时的编码 -->
<maven.compiler.encoding>UTF-8</maven.compiler.encoding>
<aspectj.version>1.9.2</aspectj.version>
在maven中写入以下信息
<build>
<plugins>
<plugin>
<!-- maven-surefire-plugin 配合testng/junit执行测试用例的maven插件 -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
<configuration>
<!-- 测试失败后,是否忽略并继续测试 -->
<testFailureIgnore>true</testFailureIgnore>
<suiteXmlFiles>
<!-- testng配置文件名称 -->
<suiteXmlFile>testng.xml</suiteXmlFile>
</suiteXmlFiles>
<!--设置参数命令行 -->
<argLine>
<!-- UTF-8编码 -->
-Dfile.encoding=UTF-8
<!-- 配置拦截器 -->
-javaagent:"${settings.localRepository}/org/aspectj/aspectjweaver/${aspectj.version}/aspectjweaver-${aspectj.version}.jar"
</argLine>
<systemProperties>
<property>
<!-- 配置 allure 结果存储路径 -->
<name>allure.results.directory</name>
<value>${project.build.directory}/allure-results</value>
</property>
</systemProperties>
</configuration>
<dependencies>
<!-- aspectjweaver maven坐标 -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>${aspectj.version}</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
进入项目文件夹,运行黑窗口,输入以下命令
//需要每个脚本都执行完提示成功再接着执行下一个,第三个命令执行完后会自动打开浏览器,可以看到allure报表
mvn clean//如果运行成功是只有绿色和蓝色的
mvn test //如果运行成功是只有绿色和蓝色的
mvn io.qameta.allure:allure-maven:serve//运行成功自动打开浏览器,显示allure报告
8. 失败截图
8.1 导入依赖
<!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.11.0</version>
</dependency>
8.2 编写截图方法
1.在WebDriverUtils中编写截图方法
//截图方法
public static void takeScreenShots(){
//WebDriver extents RemoteWebDriver,而RemoteWebDriver implements TakesScreenshot
TakesScreenshot screenshot = (TakesScreenshot) webDriver;
//截图保存成file
File srcFile = screenshot.getScreenshotAs(OutputType.FILE);
File destFile = new File("D:screenShot/webAutoScreenShot/001.png");//截图保存位置
try {
FileUtils.copyFile(srcFile,destFile);
} catch (IOException e) {
e.printStackTrace();
}
}
2.在测试用例中调用截图方法,然后测试是否可用,没问题的话是可以在我们设置的路径下找到截图的
//截图
WebDriverUtils.takeScreenShots();
8.3 监听器
1.新建一个listener包,新建一个TestResultListener类,继承TestListenerAdapter类,重写onTestSuccess、onTestFailure这两个方法
@Override
public void onTestFailure(ITestResult tr) {
super.onTestFailure(tr);
String filePath = System.getProperty("user.dir") + "/target/screenShot/";
String fileName = System.currentTimeMillis()+".png";
WebDriverUtils.takeScreenShots();
}
2.修改WebDriverUtils包下的截图方法,加入参数,测试用例中的截图方法可以删掉了
//截图方法
public static void takeScreenShots(String filePath){
//WebDriver extents RemoteWebDriver,而RemoteWebDriver implements TakesScreenshot
TakesScreenshot screenshot = (TakesScreenshot) webDriver;
//截图保存成file
File srcFile = screenshot.getScreenshotAs(OutputType.FILE);
File destFile = new File(filePath);
//省略其他代码......
3.testng.xml文件中添加监听器配置
<?xml version="1.0" encoding="UTF-8"?>
<suite name="Suite" parallel="false">
<test name="Test">
<!-- 统一配置浏览器类型 -->
<parameter name="browserName" value="chrome"/>
<classes>
<class name="testcase.TestCaseLogin"/>
</classes>
</test> <!-- Test -->
<listeners>
<listener class-name="listener.TestResultListener"/>
</listeners>
</suite> <!-- Suite -->
8.4 截图加入Allure报告
1.在WebDriverUtils类中新增一个截图方法,后面截图嵌入allure需要用到
//新建一个截图方法返回byte数组供allure报表使用
public static byte[] takeScreenShots(){
TakesScreenshot screenshot = (TakesScreenshot) webDriver;
//截图保存成BYTES
byte[] arr= screenshot.getScreenshotAs(OutputType.BYTES);
return arr;
}
在listener中添加一个AllureReportListener 实现了IHookable类,并编写一个嵌入allure报表的截图方法
package listener;
import io.qameta.allure.Attachment;
import org.testng.IHookCallBack;
import org.testng.IHookable;
import org.testng.ITestResult;
import utils.WebDriverUtils;
public class AllureReportListener implements IHookable {
@Override
public void run(IHookCallBack iHookCallBack, ITestResult iTestResult) {
//执行testng的test注解
iHookCallBack.runTestMethod(iTestResult);
//如果@test测试案例出现异常就截图
if (iTestResult.getThrowable()!=null){
//调用截图方法截图
saveScreenShots();
}
}
//编写截图方法 通过@Attachment附件功能,嵌入allure报表 可参考allure官网
@Attachment(value = "Page screenshot",type = "image/png")
public byte[] saveScreenShots(){
return WebDriverUtils.takeScreenShots();
}
}
在testng中加入allure监听器,不再重复了
每加一个监听器都要在testng中配置!
每加一个监听器都要在testng中配置!
每加一个监听器都要在testng中配置!
修改一下断言,使用例失败,测试一下功能,可以在allure报告的TestBody中成功看到截图
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-m3ARvpyP-1644916673901)(javaWeb学习总结.assets/image-20220122112429999.png)]
8.5 失败重试
1.utils包下新建一个TestRetry类,实现IRetryAnalyzer类,然后重写方法
package utils;
import org.testng.IRetryAnalyzer;
import org.testng.ITestResult;
public class TestRetry implements IRetryAnalyzer {
@Override
public boolean retry(ITestResult iTestResult) {
// testng框架自带,默认失败不会重试,把返回值改为true,则会重试
return true;
}
}
这样是有问题的,如果一直失败就会一直重试,这不是我们想要的,所以要加入一些逻辑
package utils;
import org.apache.log4j.Logger;
import org.testng.IRetryAnalyzer;
import org.testng.ITestResult;
public class TestRetry implements IRetryAnalyzer {
private final Logger logger = Logger.getLogger(TestRetry.class);
private int currentRetryCount = 1;
@Override
public boolean retry(ITestResult iTestResult) {
if (currentRetryCount <=2) {
logger.info("----------------------这是第【" + currentRetryCount + "】次重试!");
currentRetryCount++;
return true;
}else {
return false;
}
}
}
在测试用例的test注解中加入
retryAnalyzer = TestRetry.class
运行一下程序,看看已经配置的功能有没有生效,现在黑窗口运行会有日志输出,失败会截图,并且会重试,失败的截图和重试次数allure报告中都可以看到
8.6 设置全局监听
如果要我们一个一个的去给每一个测试用例加入重试,那太浪费时间了,设置全局监听就可以让所有的测试用例全部拥有重试功能
新建一个TestRetryListener类,实现IAnnotationTransformer 并重写他的方法(这里可能会有一个问题,如果以后遇到了自行解决吧)
package listener;
import org.testng.IAnnotationTransformer;
import org.testng.annotations.ITestAnnotation;
import utils.TestRetry;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
public class TestRetryListener implements IAnnotationTransformer {
@Override
public void transform(ITestAnnotation annotation, Class testClass, Constructor testConstructor, Method testMethod) {
//给所有的@Test注解的测试用例加入重试
annotation.setRetryAnalyzer(TestRetry.class);
}
}
这个时候我们可以去掉测试用例注解中的重试了,然后运行一下看看有没有重试(Oh,Shit,我忘了加监听器了)
好的,加入监听器后,运行成功了,但是有一个新问题,我们的重试次数是累计的,我们需要每次运行测试用例后初始化他的值
在TestResultListener中加入重置次数的代码(注意!我们之前私有化的当前运行次数,所以需要先把他改成公共的)
package listener;
import org.testng.ITestResult;
import org.testng.TestListenerAdapter;
import utils.TestRetry;
import utils.WebDriverUtils;
public class TestResultListener extends TestListenerAdapter {
@Override
public void onTestSuccess(ITestResult tr) {
super.onTestSuccess(tr);
//重置重试次数
TestRetry.currentRetryCount=1;
}
@Override
public void onTestFailure(ITestResult tr) {
super.onTestFailure(tr);
String filePath = System.getProperty("user.dir") + "/target/screenShot/";
String fileName = System.currentTimeMillis()+".png";
WebDriverUtils.takeScreenShots(filePath+fileName);
//重置重试次数
TestRetry.currentRetryCount=1;
}
}
好了,到这里就结束了,前辈最后一章说遗留了一个问题,不过我还没遇到,有兴趣的可以去看看https://blog.csdn.net/Keep_Learn2020/article/details/109209333
最后再次感谢前辈的分享!
入监听器后,运行成功了,但是有一个新问题,我们的重试次数是累计的,我们需要每次运行测试用例后初始化他的值
在TestResultListener中加入重置次数的代码(注意!我们之前私有化的当前运行次数,所以需要先把他改成公共的)
package listener;
import org.testng.ITestResult;
import org.testng.TestListenerAdapter;
import utils.TestRetry;
import utils.WebDriverUtils;
public class TestResultListener extends TestListenerAdapter {
@Override
public void onTestSuccess(ITestResult tr) {
super.onTestSuccess(tr);
//重置重试次数
TestRetry.currentRetryCount=1;
}
@Override
public void onTestFailure(ITestResult tr) {
super.onTestFailure(tr);
String filePath = System.getProperty("user.dir") + "/target/screenShot/";
String fileName = System.currentTimeMillis()+".png";
WebDriverUtils.takeScreenShots(filePath+fileName);
//重置重试次数
TestRetry.currentRetryCount=1;
}
}
好了,到这里就结束了,前辈最后一章说遗留了一个问题,不过我还没遇到,有兴趣的可以去看看https://blog.csdn.net/Keep_Learn2020/article/details/109209333
最后再次感谢前辈的分享!