Java&Selenium&TestNG&ZTestReport|Java&Selenium&TestNG&ZTestReport 自动化测试并生成HTML自动化测试报告

一、摘要
本篇博文将介绍如何借助ZTestReport和HTML模版,生成HTML测试报告的ZTestReport 源码Clone地址为 https://github.com/zhangfei19841004/ztest,其中ZTestReport.java
和其template是我们需要的关键。
二、ZTestReport.java
根据我的需要,在源码基础上进行了稍微修改,其中几个注释的地方需要注意,将其集成进自己的自动化框架时需要做相应的修改

package util; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import org.testng.*; import org.testng.xml.XmlSuite; import java.io.*; import java.text.SimpleDateFormat; import java.util.*; import java.util.regex.Matcher; public class TestReport implements IReporter { private long currentTime = System.currentTimeMillis(); private SimpleDateFormat formatter = new SimpleDateFormat ("yyyy年-MM月-dd日-HH时mm分ss秒"); private Date date = new Date(currentTime); private String reportdate = formatter.format(date); // 定义生成测试报告的路径和文件名,为兼容Windows和Linux此处使用File.separator代替分隔符 private String path = System.getProperty("user.dir")+File.separator+reportdate+".html"; // 定义html样式模板所在路径 private String templatePath = System.getProperty("user.dir")+File.separator+"template"; private int testsPass = 0; private int testsFail = 0; private int testsSkip = 0; private String beginTime; private long totalTime; private String name = "PaaS平台自动化测试"; /** public TestReport(){ long currentTime = System.currentTimeMillis(); SimpleDateFormat formatter = new SimpleDateFormat ("yyyy年-MM月-dd日-HH时mm分ss秒"); Date date = new Date(currentTime); name = formatter.format(date); }public TestReport(String name){ this.name = name; if(this.name==null){ long currentTime = System.currentTimeMillis(); SimpleDateFormat formatter = new SimpleDateFormat ("yyyy年-MM月-dd日-HH时mm分ss秒"); Date date = new Date(currentTime); this.name = formatter.format(date); } } */ @Override public void generateReport(List xmlSuites, List suites, String outputDirectory) { List list = new ArrayList(); for (ISuite suite : suites) { Map suiteResults = suite.getResults(); for (ISuiteResult suiteResult : suiteResults.values()) { ITestContext testContext = suiteResult.getTestContext(); IResultMap passedTests = testContext.getPassedTests(); testsPass = testsPass + passedTests.size(); IResultMap failedTests = testContext.getFailedTests(); testsFail = testsFail + failedTests.size(); IResultMap skippedTests = testContext.getSkippedTests(); testsSkip = testsSkip + skippedTests.size(); IResultMap failedConfig = testContext.getFailedConfigurations(); list.addAll(this.listTestResult(passedTests)); list.addAll(this.listTestResult(failedTests)); list.addAll(this.listTestResult(skippedTests)); list.addAll(this.listTestResult(failedConfig)); } } this.sort(list); this.outputResult(list); }private ArrayList listTestResult(IResultMap resultMap) { Set results = resultMap.getAllResults(); return new ArrayList(results); }private void sort(List list) { Collections.sort(list, new Comparator() { @Override public int compare(ITestResult r1, ITestResult r2) { if (r1.getStartMillis() > r2.getStartMillis()) { return 1; } else { return -1; } } }); }private void outputResult(List list) { try { List listInfo = new ArrayList(); int index = 0; for (ITestResult result : list) { String tn = result.getTestContext().getCurrentXmlTest().getParameter("testCase"); if(index==0){ SimpleDateFormat formatter = new SimpleDateFormat ("yyyy-MM-dd HH:mm:ss"); beginTime = formatter.format(new Date(result.getStartMillis())); index++; } long spendTime = result.getEndMillis() - result.getStartMillis(); totalTime += spendTime; String status = this.getStatus(result.getStatus()); List log = Reporter.getOutput(result); for (int i = 0; i < log.size(); i++) { log.set(i, log.get(i).replaceAll("\"", "\\\\\"")); } Throwable throwable = result.getThrowable(); if(throwable!=null){ log.add(throwable.toString().replaceAll("\"", "\\\\\"")); StackTraceElement[] st = throwable.getStackTrace(); for (StackTraceElement stackTraceElement : st) { log.add(("" + stackTraceElement).replaceAll("\"", "\\\\\"")); } } ReportInfo info = new ReportInfo(); info.setName(tn); info.setSpendTime(spendTime+"ms"); info.setStatus(status); info.setClassName(result.getInstanceName()); info.setMethodName(result.getName()); info.setDescription(result.getMethod().getDescription()); info.setLog(log); listInfo.add(info); } Map result = new HashMap(); result.put("testName", name); result.put("testPass", testsPass); result.put("testFail", testsFail); result.put("testSkip", testsSkip); result.put("testAll", testsPass+testsFail+testsSkip); result.put("beginTime", beginTime); result.put("totalTime", totalTime+"ms"); result.put("testResult", listInfo); Gson gson = new GsonBuilder().disableHtmlEscaping().setPrettyPrinting().create(); String template = this.read(templatePath); BufferedWriter output = new BufferedWriter( new OutputStreamWriter(new FileOutputStream(new File(path)),"UTF-8")); template = template.replaceFirst("\\$\\{resultData\\}", Matcher.quoteReplacement(gson.toJson(result))); output.write(template); output.flush(); output.close(); } catch (IOException e) { e.printStackTrace(); }}private String getStatus(int status) { String statusString = null; switch (status) { case 1: statusString = "成功"; break; case 2: statusString = "失败"; break; case 3: statusString = "跳过"; break; default: break; } return statusString; }public static class ReportInfo {private String name; private String className; private String methodName; private String description; private String spendTime; private String status; private List log; public String getName() { return name; }public void setName(String name) { this.name = name; }public String getClassName() { return className; }public void setClassName(String className) { this.className = className; }public String getMethodName() { return methodName; }public void setMethodName(String methodName) { this.methodName = methodName; }public String getSpendTime() { return spendTime; }public void setSpendTime(String spendTime) { this.spendTime = spendTime; }public String getStatus() { return status; }public void setStatus(String status) { this.status = status; }public List getLog() { return log; }public void setLog(List log) { this.log = log; }public String getDescription() { return description; }public void setDescription(String description) { this.description = description; }}private String read(String path) { File file = new File(path); InputStream is = null; StringBuffer sb = new StringBuffer(); try { is = new FileInputStream(file); int index = 0; byte[] b = new byte[1024]; while ((index = is.read(b)) != -1) { sb.append(new String(b, 0, index)); } return sb.toString(); } catch (FileNotFoundException e) {e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { try { if (is != null) { is.close(); } } catch (IOException e) { e.printStackTrace(); } } return null; } }

三、template 【Java&Selenium&TestNG&ZTestReport|Java&Selenium&TestNG&ZTestReport 自动化测试并生成HTML自动化测试报告】template文件是和ZTestReport.java一起使用的,他可以将TestNG的测试结果按照template的样式转换成HTML格式的报告
四 创建监听类
package com.test.listener; import com.hand.utils.ScreenShot; import com.test.BaseTest; import lombok.extern.slf4j.Slf4j; import org.openqa.selenium.WebDriver; import org.testng.ITestContext; import org.testng.ITestResult; import org.testng.TestListenerAdapter; import org.testng.annotations.Listeners; @Slf4j public class TestLogListener extends TestListenerAdapter { @Override public void onStart(ITestContext iTestContext) { super.onStart( iTestContext ); log.info( String.format( "====================%s测试开始====================", iTestContext.getName() ) ); }@Override public void onTestStart(ITestResult iTestResult) { super.onTestStart( iTestResult ); log.info( String.format( "========%s.%s测试开始========", iTestResult.getInstanceName(), iTestResult.getName()) ); }@Override public void onTestSuccess(ITestResult iTestResult) { super.onTestSuccess( iTestResult ); log.info( String.format( "========%s.%s测试通过========", iTestResult.getInstanceName(), iTestResult.getName()) ); }@Override public void onTestFailure(ITestResult iTestResult) { WebDriver driver = BaseTest.driverBase.getDriver(); System.out.print( "report_driver_fail:" + driver ); super.onTestFailure( iTestResult ); log.error( String.format( "========%s.%s测试失败,失败原因如下:\n%s========", iTestResult.getInstanceName(), iTestResult.getName(), iTestResult.getThrowable() )); // 失败截图 ScreenShot.takeScreenShot( driver,iTestResult); }@Override public void onTestSkipped(ITestResult iTestResult) { super.onTestSkipped( iTestResult ); log.info( String.format( "========%s.%s跳过测试========", iTestResult.getInstanceName(), iTestResult.getName()) ); }@Override public void onFinish(ITestContext iTestContext) { super.onFinish( iTestContext ); log.info( String.format( "====================%s测试结束====================", iTestContext.getName() ) ); } }

五设置监听
两种方法:1在代码中设置 //固定写法你的监听类(继承TestListenerAdapter的类) @Listeners({ com.example.MyListener.class, com.example.MyMethodInterceptor.class }) public class MyTest {//测试类 // ... } 二:在xml文件中声名

六拓展截图
package com.hand.utils; import org.apache.commons.io.FileUtils; import org.openqa.selenium.OutputType; import org.openqa.selenium.TakesScreenshot; import org.openqa.selenium.WebDriver; import org.testng.ITestResult; import java.io.File; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.regex.Matcher; import java.util.regex.Pattern; public class ScreenShot{ private static String screenShotDirPath = System.getProperty("user.dir") + File.separator +"target" + File.separator + "test-output" + File.separator + "errorScreenShot"; public static void takeScreenShot(WebDriver driver,ITestResult iTestResult) { Object currentClass = iTestResult.getInstance(); // 获取当前 Object 类型的测试类 //获取包名 String packageName = currentClass.getClass().getPackage().getName(); System.out.println("packageName : " + packageName); /*//根据获得的类名,去掉包名 String currentClassName = currentClass.toString().replaceAll(packageName,""); System.out.println("currentClassName : " + currentClassName); */ String currentClassName = currentClass.toString(); //正则匹配 Pattern pattern = Pattern.compile(packageName+".(.*?)@"); //此处为正则表达式 Matcher matcher = pattern.matcher(currentClassName); //去匹配正则表达式 while (matcher.find()) { currentClassName = matcher.group(1); System.out.println("currentClassName:" + currentClassName); } //System.out.println("出错的类为:" + currentClassStr); File screenShotDir = new File(screenShotDirPath); if (!screenShotDir.exists() && !screenShotDir.isDirectory()) { screenShotDir.mkdirs(); } //SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy年-MM月-dd日-HH时-mm分-ss秒SSS"); SimpleDateFormat simpleDateFormat = new SimpleDateFormat("HH点mm分ss秒"); String time = simpleDateFormat.format(new Date()); try { File source_file = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE); // 屏幕截图 //System.out.println("出错的截图命名为:" + currentClass.toString() + ".png"); FileUtils.copyFile(source_file, new File(screenShotDirPath + File.separator + currentClassName + time + ".png")); // 另存截图 } catch (IOException e) { e.printStackTrace(); } } }

    推荐阅读