您的位置:首页 > Web前端 > HTML

TestNG监听器实现失败自动截图、重跑、自定义html结果文件功能

2015-01-14 18:13 316 查看
使用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、具体的测试类中添加失败重跑监听

@Test(description = "***", retryAnalyzer = TestngRetry.class)

上面两步就可以实现失败自动重跑了,是不是比较方便,不过添加了重跑功能后会发现测试结果的邮件中用例的个数增加了,比如我只有一个用例,失败重跑了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、在build.xml文件中关闭使用默认的监听器

useDefaultListeners="false"

<testng outputDir="test-output" classpathref="http://kongqingyun123.blog.163.com/blog/runpath" haltonfailure="false" useDefaultListeners="false" >

<xmlfileset dir="." includes="${testngxml}.xml" />

</testng>

4、在testng.xml文件中添加自己重写的监听器路径
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐