jacoco 覆盖率与 git diff 结合的应用实践

上一篇 / 下一篇  2018-05-04 17:31:50 / 个人分类:覆盖率测试

  前言
  覆盖率是衡量测试质量的一个指标,但在版本高速迭代的互联网应用中,单纯通过代码覆盖率的数值是无法体现测试实际覆盖的问题,尤其是版本之间的diff,而且研发也并不会仔细的去看每行代码的覆盖.所以有了覆盖率与git diff结合的想法,通过查看功能测试中版本代码变更的部分是否覆盖,更高效的利用覆盖率,保证变更功能被测试覆盖
  覆盖率的收集
  覆盖率使用的jacoco 关于jacoco手工测试生成:
  Android 手工测试代码覆盖率增强版
  根据q博的方式略做了修改,在应用中加了隐藏开关,并在退出应用时统计覆盖率并上传到服务器.这里用的是ftp,虽然有点过时,但还算方便~
  代码很简单,就不贴了.
  class文件的收集
  jacoco的生成需要对应的class文件,所以需要在编译打包时将class文件上传
  dependencies {
      ftpAntTask("org.apache.ant:ant-commons-net:1.8.4") {
          module("commons-net:commons-net:1.4.1") {
              dependencies "oro:oro:2.0.8:jar"
          }
      }
  }
  def remotedir = "Class/"  //ftp目录
  //def hostname = "10.0.100.210"
  def hostname = "10.0.0.243"
  def username = "uftp"
  def password = "111111"
  task uploadFTP << {
      //上传至FTP
      remotedir += innerVersion
      ant {
          taskdef(name: 'ftp',
                  classname: 'org.apache.tools.ant.taskdefs.optional.net.FTP',
                  classpath: configurations.ftpAntTask.asPath)
          ftp(server: hostname,
                  userid: username,
                  password: password,
                  remotedir: remotedir,
                  action: 'mkdir')
          ftp(server: hostname,
                  userid: username,
                  password: password,
                  remotedir: remotedir) {
              fileset(dir: "./build/intermediates/classes") {
              }
          }
      }
  }
  在jenkins上覆盖率报告生成
  首先在job里添加了三个可选参数,用于选择新旧版本以及分支
  构建时进行jacoco文件的合并和报告的生成,并调用我写的java程序改造报告。
  # generate jacoco report
  gradle jacocoMerge --stacktrace
  gradle jacocoTestReport
  # generate final report
  java -jar ~/work/gitdiff.jar -r $OldVersion $NewVersion -j build/reports/jacoco/jacocoTestReport/html -p src/main/java
  cp -r ~/work/.resources build/reports/jacoco/jacocoTestReport/
  在程序中调用git diff, 并对结果进行解析
  public HashMap<String,FileDiff> parseGitDiff()
       {
           HashMap<String,FileDiff> fileMap=new HashMap<String,FileDiff>();
           ArrayList<String> curFile=new ArrayList<String>();
           for (int i = 0; i < diffList.size(); i++) {
               curFile.add(diffList.get(i));
              if((i+1)==diffList.size()||diffList.get(i+1).startsWith(GIT_FLAG))
              {
                  FileDiff diff=new FileDiff(curFile);
                  fileMap.put(diff.getId(), diff);
                  curFile=new ArrayList<String>();
              }
          }
           return fileMap;
       }
  public ArrayList<LineDiff> parseLineDiff(ArrayList<String> files)
      {
          ArrayList<LineDiff> diff=new ArrayList<LineDiff>();
          boolean isStart=false;
          String frontLine="";
          for (int i = 0; i < block.size(); i++) {
              String line=block.get(i);
              if((i+1)<block.size()&&block.get(i+1).startsWith(MINUS_FLAG)&&!isStart)
              {
                  isStart=true;
                  frontLine=block.get(i);
              }
              if(line.startsWith(MINUS_FLAG)&&isStart)
              {
                  LineDiff lineDiff=new LineDiff(frontLine, line,LineDiff.Type.Minus);
                  diff.add(lineDiff);
              }
              if(i>1&&!block.get(i-1).startsWith(MINUS_FLAG)&&!line.startsWith(MINUS_FLAG))
              {
                  frontLine=block.get(i-1);
                  isStart=false;
              }
              if(line.startsWith(PLUS_FLAG))
              {
                  LineDiff lineDiff=new LineDiff(frontLine,line,LineDiff.Type.Plus);
                  diff.add(lineDiff);
              }
          }
          return diff;
      }
  代码写的不太好,能力强的同学可以忽略~
  将git diff提取出来后找到对应覆盖率html并写入.从而产生了一个只有代码变更文件的list
  效果:
  然后更改jacoco原来的prettify.js文件,对变更代码进行标记
  function showDef (defLine) {
      var beginLine = defLine[0].substring(1);
      var between = defLine[1];
      var target = document.getElementsByClassName('linenums')[3];
      var defDom = document.createElement('div');
      var beginDom = target.getElementsByTagName('li')[beginLine - 1];
      with(defDom.style){
        position = 'absolute';
        left = '9px';
        top = beginDom.offsetTop + 16 + 'px';
        backgroundColor = '#0f0';
        pacity = '.3';
        width = '40px';
        height = 15 * between + 'px';
      };
      defDom.id = 'def' + beginLine;
      document.documentElement.appendChild(defDom);
    }
  对变更代码进行跳转
  function showDefLine () {
      var content = window['CONTENT'];
      var def = content.match(/@@(.*[^@@])/g);
      for (var i = def.length - 1; i >= 0; i--) {
        var _def = def[i].replace(/@@/g, '').split(' ');
        showDef(_def[2].split(','));
      };
      var sourceDom = document.getElementsByClassName('linenums')[1];
      sourceDom = sourceDom.getElementsByTagName('span');
      for (var i = sourceDom.length - 1; i >= 0; i--) {
        if(sourceDom[i].innerHTML === '@@'){
          sourceDom[i].parentNode.onclick = function () {
            document.body.scrollTop = document.getElementById('def' + this.getElementsByTagName('span')[9].innerHTML).offsetTop - 100;
          }
        }
      };
    }
  修改后的效果如下,页面top显示diff代码

  左侧绿色标记diff代码




TAG:

 

评分:0

我来说两句

显示全部

:loveliness: :handshake :victory: :funk: :time: :kiss: :call: :hug: :lol :'( :Q :L ;P :$ :P :o :@ :D :( :)

日历

« 2018-06-22  
     12
3456789
10111213141516
17181920212223
24252627282930

数据统计

  • 访问量: 3656
  • 日志数: 25
  • 建立时间: 2017-07-24
  • 更新时间: 2018-06-08

RSS订阅

Open Toolbar