首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >走进Java接口测试之TestNg自定报告简单学习

走进Java接口测试之TestNg自定报告简单学习

作者头像
高楼Zee
发布2019-10-22 22:57:28
8680
发布2019-10-22 22:57:28
举报
文章被收录于专栏:7DGroup7DGroup7DGroup

背景

Testng报告是否可以自定义,后面通过查找资料便有了如下自定义报告,testng中提供很多接口,如果需要改造成自己报告只要实现他们的接口即可,以下是根据自己想法实现如下自定义testng报告,如果大家感兴趣,可以根据自己需求修改。也可以把这些数据存储到数据库,之后通过一定规则即可展示出来

注意中间{ echarts.min.js }需要到网上找下放到对应目录即可。

参考代码:

import org.testng.*;import org.testng.annotations.Test;import org.testng.reporters.HtmlHelper;import org.testng.xml.XmlSuite;
import java.io.File;import java.io.IOException;import java.nio.file.Files;import java.nio.file.Paths;import java.nio.file.StandardOpenOption;import java.text.SimpleDateFormat;import java.util.*;
/** * @author 李文 * @Title: thReporter * @Description: 自定义测试报告 * @date 2019/3/15 / 9:45 */publicclassThReporterimplementsIReporter{
/**     * 获取系统信息     */privatestaticProperties sysProperty = System.getProperties();         /**     * 报告路径     */privateString reportPath;/**     * 接口类型     */privateStringMobile_phone= "SOA层自动化";/**     * 版本号     */privateString package_name = "2.9.0";/**  *//**     * 通过     */privatestaticintPassed= 0;/**     * 失败     */privatestaticintFailed= 0;/**     * 跳过     */privatestaticintSkipped= 0;/**     * 用例总共合计     */privatestaticintCountNum= 0;/**     * 通过结果     */privatestaticStringPssResuTmp, PassgetName;/**     * 开始时间     */privatestaticStringStartDate;/**     * 结束时间     */privatestaticStringEndDate;/**     * 描述     */privatestaticString description;/**     * 客户端类型     */privatestaticString clienttype;
/**     * 拼接报告数据     */staticStringBuilder sb1 = newStringBuilder();
@Overridepublicvoid generateReport(List<XmlSuite> xmlSuites, List<ISuite> suites, String outputDirectory) {       
File htmlReportDir = newFile("test-output/Test-report");if(!htmlReportDir.exists()) {            htmlReportDir.mkdirs();}String reportName = formateDate() + ".html";        reportPath = htmlReportDir + "/"+ reportName;File report = newFile(htmlReportDir, reportName);if(report.exists()) {try{                report.createNewFile();} catch(IOException e) {                e.printStackTrace();}}
StringBuffer sb = newStringBuffer();String title = "SOA层自动化";/**浏览器兼容型添加 http://www.ichartjs.com/ichart.latest.min.js */        sb.append("<!Doctype >\n<head><meta http-equiv=Content-Type content=\"text/html;charset=utf-8\"><script src='echarts.min.js'></script><meta http-equiv=X-UA-Compatible content=\"IE=edge,chrome=1\"><meta content=always name=referrer><title>UI自动化测试报告</title>").append(HtmlHelper.getCssString(".")).append("</head><body style=\"background-color:#FAEBD7;\">\n").append("<h2><p align='center'>").append(title).append("</p></h2>\n").append("<table cellspacing='0' cellpadding='0' border='1' width='90%'>").append("<tr><th>接口类型</th><th>版本号</th><th><font color=\"#00FF00\">通过数</th><th><font color=\"#FF0000\">失败数</th><th><font color=\"#ADFF2F\">跳过</th><th>用例数 </th><th>类数 </th><th>开始时间 </th><th>结束时间 </th></tr>\n");String res = sb.toString();try{Files.write((Paths.get(reportPath)), res.getBytes("utf-8"));} catch(IOException e) {            e.printStackTrace();}/**         * 控制台信息打印         */ThReporter.getprintinfotestng(suites);
        sb1.append("<td>"+ Mobile_phone+ "</td><td>"+ package_name + "</td>");        sb1.append("<td>"+ Passed+ "</td><td>"+ Failed+ "</td><td>"+ Skipped+ "</td><td>"+ (Passed+ Failed+ Skipped) + "</td><td>"+ CountNum+ "</td><td>"+ StartDate+ "</td><td>"+ EndDate+ "</td>\n");        sb1.append("</table><br/>").append("<pre><div id='canvasDiv'></div></pre>").append("<pre style=\"text-align:center\"><div id=\"newmain\" style=\"width: 1000px;height:300px; padding-left:50px \"></div></pre>").append("<table cellspacing='0' cellpadding='0' border='0' width='90%'>").append("<tr><th>"+ "执行用例数:"+ (Passed+ Failed+ Skipped) + "</th></tr>").append("</table>").append("<tbody style=\"word-wrap:break-word;font-weight:bold;\" align=\"center\"><h2>详 情</h2>").append("<table cellspacing='0' cellpadding='0' border='1' width='90%'>");
        sb1.append("<tr><th>序列号&nbsp;</th><th>失&nbsp;败</th><th>用例类名</th><th>详情信息</th><th>接口中文名字与验证点</th></tr>\n");/**详细失败数*/ThReporter.getFailedpped(suites);
        sb1.append("<tr><th>序列号&nbsp;</th><th>通&nbsp;过</th><th>用例类名</th><th>详情信息</th><th>接口中文名字与验证点</th></tr>\n");/**详细通过数*/ThReporter.getPassed(suites);
        sb1.append("<tr><th>序列号&nbsp;</th><th>跳&nbsp;过</th><th>用例类名</th><th>详情信息</th><th>接口中文名字与验证点</th></tr>\n");/**         * 详细跳过数         */ThReporter.getskipped(suites);
        sb1.append("</table><br/>");

代码中插入图代码

sb1.append("</tbody></table><a href=\"#top\">SOA层自动化</a></div><script type=\"text/javascript\">\n"+"    // 基于准备好的dom,初始化echarts实例\n"+"    var myChart = echarts.init(document.getElementById('newmain'));\n"+"\n"+"    // 指定图表的配置项和数据\n"+"    var option = {\n"+"        title : {\n"+"            text: 'SOA层自动化',\n"+"            subtext: '接口自动化',\n"+"            x:'center'\n"+"        },\n"+"        tooltip : {\n"+"            trigger: 'item',\n"+"            formatter: \"{a} <br/>{b} : {c} ({d}%)\"\n"+"        },\n"+"        legend: {\n"+"            text: 'SOA',\n"+"            x : 'center',\n"+"            y : 'bottom',\n"+"            subtext: '333',\n"+"            // left: 'top',\n"+"            data:['不通过','通过','跳过']\n"+"\n"+"        },\n"+"        toolbox: {\n"+"            show : true,\n"+"            feature : {\n"+"                mark : {show: true},\n"+"                dataView : {show: true, readOnly: false},\n"+"                magicType : {\n"+"                    show: true,\n"+"                    type: ['pie', 'funnel']\n"+"                },\n"+"                restore : {show: true},\n"+"                saveAsImage : {show: true}\n"+"            }\n"+"        },\n"+"        calculable : true,\n"+"        series : [\n"+"            {\n"+"                name:'SOA层自动化',\n"+"                type:'pie',\n"+"                radius : [30, 110],\n"+"                center : ['75%', '50%'],\n"+"                roseType : 'area',\n"+"                data:[\n"+"                    {value:"+ Failed+ ",name:'不通过',itemStyle:{color:'#EE0000'}},\n"+"                    {value:"+ Passed+ ",name:'通过',itemStyle:{color:'#7CFC00'}},\n"+"                    {value:"+ Skipped+ ",name:'跳过',itemStyle:{color:'#EE9572'}}\n"+"                ],\n"+"                itemStyle: {\n"+"                    emphasis: {\n"+"                        shadowBlur: 10,\n"+"                        shadowOffsetX: 0,\n"+"                        shadowColor: 'rgba(0, 0, 0, 0.5)'\n"+"                    },\n"+"                    normal: {\n"+"                        label: {\n"+"                            show: true,\n"+"                            formatter: '{b} : {c} ({d}%)'\n"+"                        },\n"+"                        labelLine: {show: true}\n"+"                    }\n"+"                }\n"+"            }\n"+"            ,{\n"+"                name:'SOA层自动化',\n"+"                type:'pie',\n"+"                radius : [20, 110],\n"+"                center : ['25%', '50%'],\n"+"                roseType : 'radius',\n"+"                label: {\n"+"                    normal: {\n"+"                        show: true\n"+"                    },\n"+"                    emphasis: {\n"+"                        show: true\n"+"                    },\n"+"                },\n"+"                lableLine: {\n"+"                    normal: {\n"+"                        show: false\n"+"                    },\n"+"                    emphasis: {\n"+"                        show: true\n"+"                    }\n"+"                },\n"+"                data:[{value:"+ Failed+ ",name:'不通过',itemStyle:{color:'#EE0000'}},\n"+"                    {value:'"+ Passed+ "',name:'通过',itemStyle:{color:'#7CFC00'}},\n"+"                    {value:"+ Skipped+ ",name:'跳过',itemStyle:{color:'#EE9572'}}],\n"+"                itemStyle: {\n"+"                    emphasis: {\n"+"                        shadowBlur: 10,\n"+"                        shadowOffsetX: 0,\n"+"                        shadowColor: 'rgba(0, 0, 0, 0.5)'\n"+"                    },\n"+"                    normal: {\n"+"                        label: {\n"+"                            show: true,\n"+"                            formatter: '{b} : {c} ({d}%)'\n"+"                        },\n"+"                        labelLine: {show: true}\n"+"                    }\n"+"                }\n"+"            }\n"+"\n"+"        ]\n"+"    };\n"+"    myChart.setOption(option);\n"+"\n"+"</script></body></html>\n");
String res1 = sb1.toString();try{Files.write((Paths.get(reportPath)), res1.getBytes("UTF-8"), StandardOpenOption.APPEND);} catch(IOException e) {            e.printStackTrace();}}

测试类结束控制台显示

/**     * 控制台信息打印     */privatestaticvoid getprintinfotestng(List<ISuite> suites) {SimpleDateFormat sf = newSimpleDateFormat("yyyy-MM-dd-HH mm-ss");
for(ISuite suite : suites) {Map<String, ISuiteResult> tests = suite.getResults();for(ISuiteResult r : tests.values()) {ITestContext overview = r.getTestContext();LogUtil.info("suite: "+ overview.getName());LogUtil.info("Stard Time: "+ sf.format(overview.getStartDate()));StartDate= sf.format(overview.getStartDate());LogUtil.info("End Time: "+ sf.format(overview.getEndDate()));EndDate= sf.format(overview.getEndDate());CountNum= overview.getAllTestMethods().length;LogUtil.info("all methods num : "+ overview.getAllTestMethods().length);
//passedPassed= overview.getPassedTests().size();LogUtil.info("passed: "+ overview.getPassedTests().size());Set<ITestResult> passedSet = overview.getPassedTests().getAllResults();
for(ITestResult p : passedSet) {                    description = p.getMethod().getConstructorOrMethod().getMethod().getAnnotation(Test.class).description();LogUtil.info("class: "+ p.getTestClass().getName() + " | method: "+ description);}
//failedFailed= overview.getFailedTests().size();LogUtil.info("failed: "+ overview.getFailedTests().size());Set<ITestResult> failedSet = overview.getFailedTests().getAllResults();for(ITestResult f : failedSet) {LogUtil.info("class: "+ f.getTestClass().getName() + " | method: "+ f.getName() + " | error: "+ f.getThrowable());}
//skippedSkipped= overview.getSkippedTests().size();LogUtil.info("skipped: "+ overview.getSkippedTests().size());Set<ITestResult> skippedSet = overview.getSkippedTests().getAllResults();for(ITestResult s : skippedSet) {LogUtil.info("---- "+ s.getName());LogUtil.info(s.getThrowable() + "");}LogUtil.info("==================================");}
}}

跳过方法编写

/**     * 详细跳过数     */publicstaticvoid getskipped(List<ISuite> suites) {/**详细跳过数*/for(ISuite suite : suites) {Map<String, ISuiteResult> tests = suite.getResults();for(ISuiteResult r : tests.values()) {ITestContext overview = r.getTestContext();CountNum= overview.getAllTestMethods().length;Set<ITestResult> skippedSet = overview.getSkippedTests().getAllResults();int i = 0;for(ITestResult s : skippedSet) {                    description = s.getMethod().getConstructorOrMethod().getMethod().getAnnotation(Test.class).description();                    sb1.append("<tr><td>"+ i + "</td><td><font color=\"FF9966\">&nbsp;跳过</font></td><td>"+ s.getName() + "</td><td>"+ "接口名字:"+ s.getThrowable() + "</td><td>验证点:"+ description + "</td>");                                        i++;}}}}

失败方法编写

/**     * 详细失败数     */publicstaticvoid getFailedpped(List<ISuite> suites) {for(ISuite suite : suites) {Map<String, ISuiteResult> tests = suite.getResults();for(ISuiteResult r : tests.values()) {ITestContext overview = r.getTestContext();CountNum= overview.getAllTestMethods().length;int i = 0;Set<ITestResult> failedSet = overview.getFailedTests().getAllResults();for(ITestResult f : failedSet) {                    description = f.getMethod().getConstructorOrMethod().getMethod().getAnnotation(Test.class).description();LogUtil.info("class: "+ f.getTestClass().getName() + " | method: "+ f.getName() + " | error: "+ f.getThrowable());                    sb1.append("<tr><td>"+ i + "</td><td><font color=\"FF0000\">&nbsp;失败</font></td><td>"+ f.getTestClass().getName() + "</td><td>"+ "测试方法名: "+ f.getName() + " 失败详情: "+ f.getThrowable() + "</td><td>验证点:"+ description + "</td>");                                        i++;}}}

通过方法编写

/**     * 详细通过数     */publicstaticvoid getPassed(List<ISuite> suites) {for(ISuite suite : suites) {Map<String, ISuiteResult> tests = suite.getResults();for(ISuiteResult r : tests.values()) {ITestContext overview = r.getTestContext();CountNum= overview.getAllTestMethods().length;Set<ITestResult> passedSet = overview.getPassedTests().getAllResults();
int i = 0;for(ITestResult p : passedSet) {LogUtil.info("class: "+ p.getTestClass().getName() + " | method: "+ p.getName());PssResuTmp= p.getTestClass().getName();PassgetName= p.getName();                    description = p.getMethod().getConstructorOrMethod().getMethod().getAnnotation(Test.class).description();/**获取客户端类型如果安卓、pc版本*/                    clienttype = p.getMethod().getConstructorOrMethod().getMethod().getAnnotation(Test.class).testName();                    sb1.append("<tr><td>"+ i + "</td><td><font color=\"#00FF00\">&nbsp;通 过</font></td><td>"+ PssResuTmp+ "</td><td>"+ "接口名字:"+ PassgetName+ "</td><td>验证点:"+ description + "</td>");                                        i++;}}}}

日期格式化方法

/**     * 日期格式化     *     * @return date     */publicstaticString formateDate() {SimpleDateFormat sf = newSimpleDateFormat("yyyy-MM-dd-HH-mm-ss");Calendar cal = Calendar.getInstance();Date date = cal.getTime();return sf.format(date);}

/**     * 日期格式化     *     * @return date     */privatestaticString formatDate(long date) {SimpleDateFormat formatter = newSimpleDateFormat("yyyy-MM-dd HH:mm:ss");return formatter.format(date);}

监听写好后,通过xml配置即可。

<suitename="First suite"verbose="1"><listeners><listenerclass-name="com.threport.ThReporter"/></listeners>
<testname="接口测试报告"><packages><packagename="执行的包名"/></packages></test></suite>

在这里引用屈原《离骚》"路漫漫其修远兮,吾将上下而求索"。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-10-20,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 7DGroup 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 参考代码:
    • 代码中插入图代码
      • 测试类结束控制台显示
        • 跳过方法编写
          • 失败方法编写
            • 通过方法编写
              • 日期格式化方法
                • 监听写好后,通过xml配置即可。
                相关产品与服务
                数据保险箱
                数据保险箱(Cloud Data Coffer Service,CDCS)为您提供更高安全系数的企业核心数据存储服务。您可以通过自定义过期天数的方法删除数据,避免误删带来的损害,还可以将数据跨地域存储,防止一些不可抗因素导致的数据丢失。数据保险箱支持通过控制台、API 等多样化方式快速简单接入,实现海量数据的存储管理。您可以使用数据保险箱对文件数据进行上传、下载,最终实现数据的安全存储和提取。
                领券
                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档