Java语言搭建Web自动化框架学习十三(TestNG监听机制)

it2025-03-16  11

TestNG监听机制

需求背景:失败案例进行截图核心代码13.1新建Listener包,新建TestRusultListener类13.2修改testng.xml,使监听器生效 需求背景:截图嵌入allure报表核心代码13.3新建AllureReportListener类 问题解决13.1截图未嵌入报表 需求背景:失败案例重试核心代码13.4新建一个TestRetry13.5增加重试次数逻辑13.6设置全局失败监听重试 问题解决13.2监听重试和dataprovider多行数据冲突(未解决) 学习心得

需求背景:失败案例进行截图

核心代码

13.1新建Listener包,新建TestRusultListener类

public class TestResultListener extends TestListenerAdapter{ @Override public void onTestFailure(ITestResult tr) { // TODO Auto-generated method stub super.onTestFailure(tr); //编写自定义内容 //filePath命名解决: //保存路径,保存在项目文件夹,所以要获取项目路径 String filePath = System.getProperty("user.dir")+"\\target\\screenshot\\"; //获取时间戳 String fileName = System.currentTimeMillis()+".png"; WebDriverUtils.takeScreenshot(filePath+fileName); } }

13.2修改testng.xml,使监听器生效

<listeners> <listener class-name = "监听类路径"></listener> </listeners>

需求背景:截图嵌入allure报表

核心代码

13.3新建AllureReportListener类

注意:记得新增的监听类都要去xml对应添加listener标签对

public class AllureReportListener implements IHookable{ @Override public void run(IHookCallBack callBack, ITestResult testResult) { // TODO Auto-generated method stub //执行testng的@test注解 callBack.runTestMethod(testResult); //如果@test测试案例结果出现异常,即案例失败 if(testResult.getThrowable() != null) { //调用截图方法,进行截图 saveScreenshot(); } } //嵌入allure报表的通过@Attachment附件功能,可参考allure官网 @Attachment(value = "Page screenshot", type = "image/png") public byte[] saveScreenshot() { return WebDriverUtils.takeScreenshot(); } }

对应修改WebDriverUtils类,使返回一个byte数组

//新建一个截图方法返回byte数组,因为allure报表生成需要 public static byte[] takeScreenshot() { //强转,为什么能强转?因为WebDriver extents RemoteWebDriver,而RemoteWebDriver implements TakesScreenshot TakesScreenshot screenshot = (TakesScreenshot)driver; //截图保存成BYTES byte[] arr = screenshot.getScreenshotAs(OutputType.BYTES); return arr; }

问题解决

13.1截图未嵌入报表

忘记加监听配置,testng监听对中加AllureReportListener

需求背景:失败案例重试

核心代码

web自动化不够稳定,提高成功率

13.4新建一个TestRetry

public class TestRetry implements IRetryAnalyzer{ @Override public boolean retry(ITestResult result) { // testng框架自带,默认失败不会重试,把返回值改为true,则会重试 return true; } }

测试案例关联失败监听

@Test(retryAnalyzer = TestRetry.class)

引发问题:失败则返回为真,如果失败了,就一直重试

13.5增加重试次数逻辑

public class TestRetry implements IRetryAnalyzer{ Logger logger = Logger.getLogger(TestRetry.class); private int maxRetryCount = 2; private int currentRetryCount = 0; @Override public boolean retry(ITestResult result) { if(currentRetryCount < maxRetryCount) { currentRetryCount++; logger.info("========================================这是第【"+currentRetryCount+"】次重试==========================="); return true; }else { return false; } } }

13.6设置全局失败监听重试

新建一个TestRetryListener类,implements IAnnotationTransformer,可以获取到@Test里的注解,并且改变注解值,这个也需要在xml监听标签对中添加

public class TestRetryListener implements IAnnotationTransformer{ @Override public void transform(ITestAnnotation annotation, Class testClass, Constructor testConstructor, Method testMethod) { //获取testng@test里的RetryAnalyzer注解 IRetryAnalyzer analyzer = annotation.getRetryAnalyzer(); //如果没有这个注解,则设置这个注解为自定义的retry类,这样就实现了针对全部test的重试,而不用一个一个test去添加注解 if(analyzer == null) { annotation.setRetryAnalyzer(TestRetry.class); } } }

问题解决

13.2监听重试和dataprovider多行数据冲突(未解决)

dataprovider中有多行数据时,多次执行同一个@Test时,会被算成重试。 解决方案:当dataprovider中的一行数据被执行完后,重试次数要恢复到初始值

public class TestRetry implements IRetryAnalyzer{ Logger logger = Logger.getLogger(TestRetry.class); private int maxRetryCount = 2; public static int currentRetryCount = 1; @Override public boolean retry(ITestResult result) { logger.info("==================这是第【"+currentRetryCount+"】次重试==========================="); if(currentRetryCount <= maxRetryCount) { currentRetryCount++; logger.info("==================有运行到重试方法==========================="); return true; }else { return false; } } }

修改TestResultListener 类

public class TestResultListener extends TestListenerAdapter{ @Override public void onTestFailure(ITestResult tr) { //省略其他功能重复截图 //dataprovider中一行数据全部重试运行次数达到最大值了也还是失败的话,把失败重试次数置为1,避免下一行数据重试次数计数出问题 TestRetry.currentRetryCount = 1; } @Override public void onTestSuccess(ITestResult tr) { // TODO Auto-generated method stub super.onTestSuccess(tr); // //dataprovider中一行数据运行成功后,把失败重试次数置为1,避免下一行数据重试次数计数出问题 TestRetry.currentRetryCount = 1; } }

这样改了代码后,虽然不会把重试次数计算错了,但是遇到多行情况,出错的数据就程序报错,一次都不执行了,耗时的事情先放一放,先捋清楚大块,有空在纠小细节

学习心得

通过监听功能的学习,写代码更好的理解了java中继承父类和实现接口的一点区别 1>继承父类(别人写好的class),关键字是extends,父类里有很多方法,子类继承后可以直接使用父类方法,如果想针对父类方法个性化,就对应选择重写父类方法 2>实现接口(别人写好的interface),关键字是implements,接口里也有方法,但是子类实现接口后,必须要重写接口方法,等待子类去实现具体方法体

最新回复(0)