注: 以下内容引自 http://blog.csdn.net/sunnyyou2011/article/details/45894089 (此非原出处,亦为转载,但博主未注明原出处)

使用Testng框架搭建自动测试框架,经常会需要增加失败自动截图,以及失败重跑功能,下面介绍一下不修改Testng的源码,通过监听器的方式来实现自动截图、重跑、以及自定义生成的Html结果文件功能。

自动截图功能
1、新建一个Java类继承TestListenerAdapter
2、重写onTestFailure、onTestSkipped等方法,在这些方法中加入截图操作
3、在testng.xml文件中配置自己编写的监听器类


<listeners>

<listener class-name="***.testng.TestngListener" /> </listeners>


public class TestngListener extends TestListenerAdapter { private static Logger logger = Logger.getLogger(TestngListener.class); public static final String CONFIG = "config.properties"; @Override public void onTestFailure(ITestResult tr) { super.onTestFailure(tr); logger.info(tr.getName() + " Failure"); takeScreenShot(tr); } @Override public void onTestSkipped(ITestResult tr) { super.onTestSkipped(tr); logger.info(tr.getName() + " Skipped"); takeScreenShot(tr); } @Override public void onTestSuccess(ITestResult tr) { super.onTestSuccess(tr); logger.info(tr.getName() + " Success"); } @Override public void onTestStart(ITestResult tr) { super.onTestStart(tr); logger.info(tr.getName() + " Start"); } @Override public void onFinish(ITestContext testContext) { super.onFinish(testContext); } /** * 自动截图,保存图片到本地以及html结果文件中 * * @param tr */ private void takeScreenShot(ITestResult tr) { SimpleDateFormat formatter = new SimpleDateFormat("yyyy_MM_dd_HH_mm_ss"); String mDateTime = formatter.format(new Date()); String fileName = mDateTime + "_" + tr.getName(); String filePath = OrangeiOS.driver.getScreenshotAs(fileName); Reporter.setCurrentTestResult(tr); Reporter.log(filePath);

//这里实现把图片链接直接输出到结果文件中,通过邮件发送结果则可以直接显示图片 Reporter.log("<img src=\"../" + filePath + "\"/>"); }

失败自动重跑功能
1、新建Java类实现IRetryAnalyzer接口


public class TestngRetry implements IRetryAnalyzer { private static Logger logger = Logger.getLogger(TestngRetry.class); private int retryCount = 1; private static int maxRetryCount; private static ConfigReader config; static {

//外围文件配置最大运行次数 config = new ConfigReader(TestngListener.CONFIG); maxRetryCount = config.getMaxRunCount(); logger.info("maxRunCount=" + (maxRetryCount)); } @Override public boolean retry(ITestResult result) { if (retryCount <= maxRetryCount) { String message = "running retry for '" + result.getName() + "' on class " +

this.getClass().getName() + " Retrying " + retryCount + " times"; logger.info(message); Reporter.setCurrentTestResult(result); Reporter.log("RunCount=" + (retryCount + 1)); retryCount++; return true; } return false; } }

2、新建Java类实现IAnnotationTransformer接口


public class RetryListener implements IAnnotationTransformer { @Override public void transform(ITestAnnotation annotation, Class testClass,

Constructor testConstructor, Method testMethod) { IRetryAnalyzer retry = annotation.getRetryAnalyzer(); if (retry == null) { annotation.setRetryAnalyzer(TestngRetry.class); } } }

3、在build.xml或者testng.xml文件中添加RetryListener监听器

上面三步就可以实现失败自动重跑了,是不是比较方便,不过添加了重跑功能后会发现测试结果的邮件中用例的个数增加了,比如我只有一个用例,失败重跑了2次,一共运行3次,测试结果中显示的用例个数会是3个,那接下来就需要解决这个问题了。

首先解决TestNg生成的index.html文件中个数不对的问题,这个问题只需要在Testng监听器的onFinish方法中,等所有用例运行完之后,检查用例,按照class+method+dataprodiver的名称生成hashcode获取唯一id,如果fail的用例中存在重复的则在 fail的用例中剔除掉,具体代码如下:


@Override public void onFinish(ITestContext testContext) { super.onFinish(testContext); // List of test results which we will delete later ArrayList<ITestResult> testsToBeRemoved = new ArrayList<ITestResult>(); // collect all id's from passed test Set<Integer> passedTestIds = new HashSet<Integer>(); for (ITestResult passedTest : testContext.getPassedTests().getAllResults()) { logger.info("PassedTests = " + passedTest.getName()); passedTestIds.add(getId(passedTest)); } Set<Integer> failedTestIds = new HashSet<Integer>(); for (ITestResult failedTest : testContext.getFailedTests().getAllResults()) { logger.info("failedTest = " + failedTest.getName()); // id = class + method + dataprovider int failedTestId = getId(failedTest); // if we saw this test as a failed test before we mark as to be deleted // or delete this failed test if there is at least one passed version if (failedTestIds.contains(failedTestId) || passedTestIds.contains(failedTestId)) { testsToBeRemoved.add(failedTest); } else { failedTestIds.add(failedTestId); } } // finally delete all tests that are marked for (Iterator<ITestResult> iterator =

testContext.getFailedTests().getAllResults().iterator(); iterator.hasNext();) { ITestResult testResult = iterator.next();if (testsToBeRemoved.contains(testResult)) { logger.info("Remove repeat Fail Test: " + testResult.getName()); iterator.remove(); } } } private int getId(ITestResult result) { int id = result.getTestClass().getName().hashCode(); id = id + result.getMethod().getMethodName().hashCode(); id = id + (result.getParameters() != null ? Arrays.hashCode(result.getParameters()) : 0); return id; }

当前失败重跑也存在一些小问题:
1、setup中出现的错误直接是skip的,不会重跑
2、如果存在dataprodiver,则第二组数据以后的用例是不会重跑的
3、testng自带生成的emailable-report.html文件中用例的个数也不对了,这个问题可以自行修改EmailableReporter.java文件

如何修改自定义emailable-report.html

emailable-report.html是Testng运行完成后自动生成的,经常运行结束后我们会把这个文件作为邮件正文发送给收件人,如果我们要修改这个文件内容怎么办呢?

1、首先emailable-report.html文件的生成TestNG是实现了IReporter接口,那我们可以直接从源代码中取出这个文件源代码
https://github.com/cbeust/testng/blob/master/src/main/java/org/testng/reporters/EmailableReporter.java
2、针对源代码进行自己修改
3、把修改后的源代码加入自己的工程
4、在build.xml文件中新增自定义的监听器,运行时就会调用自定义的监听器生成想要的html文件了


<testng outputDir="test-output" classpathref="http://qa.blog.163.com/blog/runpath" haltonfailure="false" listeners="com.****.CustomerEmailableReport" > <xmlfileset dir="." includes="${testngxml}.xml" /> </testng>

TestNG监听器实现用例运行失败自动截图、重运行功能的更多相关文章

  1. TestNG实现用例运行失败自动截图(转载)

    转载自:https://blog.csdn.net/galen2016/article/details/70193684 重写Listener的onTestFailure方法 package com. ...

  2. Selenium2+python自动化67-用例失败自动截图【转载】

    前言: 装饰器其实就是一个以函数作为参数并返回一个替换函数的可执行函数 上一篇讲到用装饰器解决异常后自动截图,不过并没有与unittest结合,这篇把截图的装饰器改良了下,可以实现用例执行失败自动截图 ...

  3. testng 失败自动截图

    testng执行case failed ,testng Listener会捕获执行失败,如果要实现失败自动截图,需要重写Listener的onTestFailure方法 那么首先新建一个Listene ...

  4. QTP场景恢复之用例失败自动截图

    以下代码是在QC里运行QTP来执行脚本过程,当执行过程中发现用例失败后就会自动截图,然后把用例返回到最初始的状态,模拟了场景恢复的机制 Class QCImageErrorCapture Dim qt ...

  5. Webdriver+Testng实现测试用例失败自动截图功能

    testng执行测试用例的时候,如果用例执行失败会自动截图,方便后续排查问题 1.首先定义一个截图类: package com.rrx.utils; import java.io.File;impor ...

  6. TestNG失败自动截图

    转自:https://www.cnblogs.com/tobecrazy/p/4814813.html

  7. appium自动化,失败自动截图

    1.创建监听器类TestNGListener,重写onTestFailure方法,里面定义了 监听的driver ,截图文件路径和名称 package utils; import cases.Appi ...

  8. selenium2入门 断言失败自动截图 (四)

    一般web应用程序出错过后,会抛出异常.这个时候能截个图下来,当然是极好的. selenium自带了截图功能. //获取截图file File scrFile= ((TakesScreenshot)d ...

  9. selenium2 断言失败自动截图 (四)

    一般web应用程序出错过后,会抛出异常.这个时候能截个图下来,当然是极好的. selenium自带了截图功能. //获取截图file File scrFile= ((TakesScreenshot)d ...

随机推荐

  1. leetcode之旅(10)-Roman to Integer

    题目描述: Given a roman numeral, convert it to an integer. Input is guaranteed to be within the range fr ...

  2. LeetCode(45)-Bulls and Cows

    题目: You are playing the following Bulls and Cows game with your friend: You write down a number and ...

  3. Which SQL statement is the trump card to the senior software developer

    Which SQL statement is the trump card to the senior software developer                    MA Genfeng ...

  4. DIV与SPAN之间有什么区别

    DIV与SPAN之间有什么区别 DIV 和 SPAN 元素最大的特点是默认都没有对元素内的对象进行任何格式化渲染.主要用于应用样式表(共同点). 两者最明显的区别在于DIV是块元素,而SPAN是行内元 ...

  5. pt-align

    pt-align的功能很简单,将其它工具的输出按列对其. 用法: pt-align [FILES] 如果没有指定文件,则默认读取标准输入的内容. 如,常用的vmstat的输出,阅读体验就不够人性化. ...

  6. 【Java入门提高篇】Day16 Java异常处理(下)

    今天继续讲解java中的异常处理机制,主要介绍Exception家族的主要成员,自定义异常,以及异常处理的正确姿势. Exception家族 一图胜千言,先来看一张图. Exception这是一个父类 ...

  7. ZeroMQ 教程 002 : 高级技巧

    本文主要译自 zguide - chapter two. 但并不是照本翻译. 上一章我们简单的介绍了一个ZMQ, 并给出了三个套路的例子: 请求-回应, 订阅-发布, 流水线(分治). 这一章, 我们 ...

  8. arcengine之版本管理

    public void VersionManagement(IVersionedWorkspace versionedWorkspace) { //creating the new version o ...

  9. (十分钟视频教程)nodejs基础实战教程3:react服务端渲染入门篇

    视频截图如下: (具体视频见文末) 前言: 这是小猫的第三篇node教程,本篇内容是由公众号粉丝票选得出的,相信大家对这篇教程是抱有较大希望的,这篇教程由小猫和一位多年的好朋友合作完成(笔名:谷雨,博 ...

  10. 创建ndarray

    Numpy最重要的一个特点就是其N维数组对象(即ndarray),该对象是一个快速而灵活的大数据集容器,是一个通用的同构数据多维容器,也就是说,其中的所有元素必须是相同类型的. 创建数组最简单的方法就 ...