精准测试系列《四》

前期分享的文章:精准测试系列《三》分享了如何通过测试管理平台进行发布分支,今天分享的内容是在发布完成后我们要触发代码覆盖率的统计的逻辑,分享的大致思路还是从前端页面发起请求,然后后端接收到请求继续处理这样的逻辑来分享的。

 

Step1:前端页面的按钮

 <button class='btn btn-warning' id='getStatist' align='center' onclick='getStatist($(this))'>统计覆盖率</button>
 
 点击后调用ajax 请求:
 function getStatist(td) {
         var tr=td.parent().parent()
         console.log(tr);
         var tdlist=tr.find("td");
         console.log(tdlist);
         var id=$(tdlist[0]).find('input').val()
        console.log(id);
        if(id.length != 0) {
            var mymessage = confirm("确定现在开始统计吗?")
            if (mymessage == true) {
                $.ajax({
                    url:'/jacoco_statist/'+id,
                    type: 'GET',
                    dataType: 'json',
                    timeout: 1000,
                    cache: false,
                    beforeSend: function () {
                        $("#mainbody").html('<div align="center">统计执行中...</div>');

                    }, //加载执行方法
                    error: function () {
                        alert('数据加载失败!!!');
                    },  //错误执行方法
                    success: function () {
                        var time=3;
                        setInterval(function () {
                            if(time==0){
                                location.href="/jacoco_index/1"
                            }else{
                                $("#mainbody").html('<div align="center">统计执行中,<span id="sid">'+time+'</span>s 自动后返回</div>');
                               time--;
                           }
                        },1000);
                    }
                })
            }
        }
}

Step2:flask路由规则

(r"/jacoco_statist/(?P<id>\d*)",JacocoStatist),

 

Step3:flask接收到请求处理如下

 class JacocoStatist(RequestHandler):
    def get(self,id):
        sql1 = "select uuid,git_url,job_branch,cover_module from jacoco_info where id=" + str(id)
        sql2 = "select uuid,git_url,job_branch,cover_module from jacoco_info"
        db = conndb()
        result = db.get_data(sql1, sql2)
        uuid = result[0]['uuid']
        git_url = result[0]['git_url']
        job_branch = result[0]['job_branch']
        cover_module = result[0]['cover_module']
        get_statist(uuid, job_branch, git_url, cover_module)
        data = {"meg": "success"}
        return self.write(data)

def async(func):
    def wrapper(*args,**kwargs):
        t1=Thread(target=func,args=args,kwargs=kwargs)
        t1.start()
    return wrapper

@async
def get_statist(uuid,branch,giturl,module):
    # 1)启动覆盖率收集
    test = HttpUtils()
    url = "http://10.7.36.35:9099/cov/triggerEnvCov"
    body = {"uuid": uuid, "type": 2, "gitUrl": giturl,
            "subModule": module, "baseVersion": "master", "nowVersion": branch,
            "address": "10.7.36.35", "port": "9098"}
    content = test.httpPost(url, body, "/cov/triggerEnvCov")
    print(content)
    return content

 

Step4:上面的flask处理过程中调用了super-jacoco的接口

接口url地址为:"http://10.7.36.35:9099/cov/triggerEnvCov"

在这里实际是调用到了super-jacoco 的 controller 服务,其代码如下:

@RequestMapping(value = "/triggerEnvCov", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
@ResponseBody
public HttpResult<Boolean> triggerEnvCov(@RequestBody @Validated EnvCoverRequest envCoverRequest) {
    codeCovService.triggerEnvCov(envCoverRequest);
    return HttpResult.success();
}

这里实际上是调用了 codeCovService 这个实现类的 triggerEnvCov 方法,其代码调用内容如下:

 @Override
 public void triggerEnvCov(EnvCoverRequest envCoverRequest) {
     try {
         CoverageReportEntity coverageReport = new CoverageReportEntity();
         coverageReport.setFrom(Constants.CoverageFrom.ENV.val());//设置from 字段为ENV(2, "环境部署");--其实就是功能测试
         coverageReport.setEnvType("");
         coverageReport.setUuid(envCoverRequest.getUuid());
         coverageReport.setGitUrl(envCoverRequest.getGitUrl());
         coverageReport.setNowVersion(envCoverRequest.getNowVersion());
        coverageReport.setType(envCoverRequest.getType());

        if (!StringUtils.isEmpty(envCoverRequest.getBaseVersion())) {
            coverageReport.setBaseVersion(envCoverRequest.getBaseVersion());
        }
        if (!StringUtils.isEmpty(envCoverRequest.getSubModule())) {
            coverageReport.setSubModule(envCoverRequest.getSubModule());
        }

        if (envCoverRequest.getBaseVersion().equals(envCoverRequest.getNowVersion()) &&
                envCoverRequest.getType() == Constants.ReportType.DIFF.val()) {//判断当前分支是否与基础分支是同一个并且是做增量代码的对比,DIFF(2, "增量覆盖率");
            coverageReport.setBranchCoverage((double) 100);// 进来了表示上面的条件成立,那么分支覆盖率就是100
            coverageReport.setLineCoverage((double) 100);//行覆盖率也是100
            coverageReport.setRequestStatus(Constants.JobStatus.NODIFF.val());//状态为 NODIFF(100, "无增量"),
            coverageReport.setErrMsg("没有增量方法");//设置msg消息
            coverageReportDao.insertCoverageReportById(coverageReport);//插入一条记录到【增量代码覆盖率】表中去
            return; //结束这个请求
        }

        coverageReport.setRequestStatus(Constants.JobStatus.WAITING.val());//WAITING(1, "待执行"),
        coverageReportDao.insertCoverageReportById(coverageReport); //插入一条记录到【增量代码覆盖率】表中去
        deployInfoDao.insertDeployId(envCoverRequest.getUuid(), envCoverRequest.getAddress(), envCoverRequest.getPort());//插入一条记录到【服务部署信息】表中去
        new Thread(() -> {//开启一个线程
            cloneAndCompileCode(coverageReport);//step1:去clone and 编译代码
            if (coverageReport.getRequestStatus() != Constants.JobStatus.COMPILE_DONE.val()) {//如果上一步执行完成后,状态不为COMPILE_DONE[(103, "编译成功")]
                log.info("{}计算覆盖率具体步骤...编译失败uuid={}", Thread.currentThread().getName(), coverageReport.getUuid()); //输出一个info级别的日志
                return;//结束这个线程处理
            }
            if (coverageReport.getType() == Constants.ReportType.DIFF.val()) {//如果是做增量代码diff,[DIFF(2, "增量覆盖率")]
                 calculateDeployDiffMethods(coverageReport);//step2:计算增量方法
                if (coverageReport.getRequestStatus() != Constants.JobStatus.DIFF_METHOD_DONE.val()) { //如果返回的执行结果状态不为DIFF_METHOD_DONE(104, "计算增量方法成功")
                    log.info("{}计算覆盖率具体步骤...计算增量代码失败,uuid={}", Thread.currentThread().getName(), coverageReport.getUuid());//输出一个info级别的日志
                    return;//结束这个线程处理
                }
            }
            calculateEnvCov(coverageReport);//step3:计算增量方法覆盖率
        }).start();//线程开始执行
    } catch (Exception e) {
        throw new ResponseException(e.getMessage());
    }
}

至此已经算是把代码覆盖率统计整体流程上讲解完成了,但是其中有三个分支上面的调用我这里就没有展开,后面会根据情况看是否需要补充。

备注:
这里的代码调用链条大家一条要清楚,首先是前端调用了后端的 python flask 接口,其次是 python flask 又调用了后端的 super-jacoco 的接口,从而完成了整体的逻辑调用。

代码分享里面我把个人理解的注释都写在备注上了,大家可以辅助理解,如有疑问可以在公众号后台留言或微信专属技术群讨论。

 

欢迎关注【无量测试之道】公众号,回复【领取资源】
Python编程学习资源干货、
Python+Appium框架APP的UI自动化、
Python+Selenium框架Web的UI自动化、
Python+Unittest框架API自动化、
资源和代码 免费送啦~
文章下方有公众号二维码,可直接微信扫一扫关注即可。

备注:我的个人公众号已正式开通,致力于测试技术的分享,包含:大数据测试、功能测试,测试开发,API接口自动化、测试运维、UI自动化测试等,微信搜索公众号:“无量测试之道”,或扫描下方二维码:

精准测试系列《四》

添加关注,让我们一起共同成长!


上一篇:为什么MySQL不推荐使用uuid作为主键?太完整了!


下一篇:接口防重复提交