代码覆盖率在性能测试中的应用

猪小花1号2018-09-17 13:01

作者:牛小宝


为什么引入代码覆盖率

在做性能测试时,需要考虑被测系统的真实使用场景,通过模拟真实的使用场景去压测才能得出具有参考意义的性能指标。而实际的测试中,有些场景却隐藏的很深,比如说下单,虽然下单接口只有一个,但是会根据入参商品的不同类型进行不同的处理逻辑,商品可能是普通商品,也可能是团购商品等,因此接口压测完之后,我们需要分析一下有没有覆盖到预期场景的代码逻辑,或者有没有遗漏的场景未覆盖。这时我们考虑到引入代码覆盖率,可以根据代码的覆盖情况分析出已测场景和未覆盖场景,从而针对性进行补测。所以在测试过程中不能只取关注代码覆盖率这个数值,而是通过代码的覆盖情况增加重要场景的覆盖度,提升性能测试的质量。


如何获得代码覆盖率数据

获取代码覆盖率的工具很多,比较流行的有Jacoco,Emma,Cobertura等,使用什么样的方式获取当然是取决于我们的需求:

  1. 可以动态获取代码覆盖率,并且对应用性能影响较小;
  2. 代码覆盖率的获取方式简单,最好可以一键式操作;
  3. 覆盖率数据可以面板展示,组里的人都可以查看;
  4. 可以自定义一些操作,比如自动拉取代码,切换分支等; 

综上考虑,采用Jenkins+jacoco获取代码覆盖率,sonar进行覆盖率的展示,Jenkins和sonar公司是有平台的,使用起来更方便;


环境搭建

应用服务器Jacoco配置:

  1. 在应用服务器上安装ant,配置环境变量,官网地址:http://ant.apache.org/
  2. 官网下载jacoco-0.7.9.zip,官网地址:http://www.eclemma.org/jacoco/
  3. 解压下载的jacoco-0.7.9.zip, 并将lib下的 jacocoagent.jar 拷贝到所要监控的应用服务器中,如:/home/qaperf/jenkinsJacoco/lib/jacocoagent.jar;
  4. 修改 ./default/tomcat,加入在JAVA_OPTS加入以下配置项,并重启tomcat
    -javaagent:/home/qaperf/jenkinsJacoco/lib/jacocoagent.jar=includes=com.netease.*,output=tcpserver,port=8893,address=127.0.0.1
    
  5. Jacoco获取代码覆盖率的方式有多种,这里采用Ant构建脚本来生成代码覆盖率的二进制文件,Ant构建脚本build.xml的内容如下:

    <?xml version="1.0" ?>
    <project name="jacoco" xmlns:jacoco="antlib:org.jacoco.ant">
     <!--Jacoco的安装路径-->
    <property name="jacocoantPath" value="./lib/jacocoant.jar"/>
    <!--最终生成.exec文件的路径,Jacoco就是根据这个文件生成最终的报告的-->
    <property name="jacocoexecPath" value="./jacoco.exec"/>
     <!--生成覆盖率报告的路径-->
    <property name="reportfolderPath" value="./report"/>
    <!--远程tomcat服务的ip地址,这里使用的是本地服务器-->
    <property name="server_ip1" value="127.0.0.1"/>
    <!--前面配置的远程tomcat服务打开的端口,要跟上面配置的一样-->
    <property name="server_port" value="8893"/>
    <!--源代码路径-->
    <property name="Srcpath" value="/home/qaperf/jenkinsJacoco/src/global-online/online-war/src/main/java" />
    <!--.class文件路径-->
    <property name="Classpath" value="/home/qaperf/haitaoTest/performance/webroot-online-Ins1/WEB-INF/classes" />
    
    <!--让ant知道去哪儿找Jacoco-->
    <taskdef uri="antlib:org.jacoco.ant" resource="org/jacoco/ant/antlib.xml">
       <classpath path="${jacocoantPath}" />
    </taskdef>
    
    <!--dump任务:
       根据前面配置的ip地址,和端口号,
       访问目标tomcat服务,并生成.exec文件。-->
    <target name="dump">
       <jacoco:dump address="${server_ip1}" destfile="${jacocoexecPath}" port="${server_port}" append="false" reset="true"/>
    </target>
    </project>
    

Jenkins配置:

  1. 新建代码覆盖率的Job,添加节点机,节点机既是已安装Jacoco的应用服务器
  2. 在构建一栏添加“Execute shell”,添加如下内容:
    #ant的构建文件build.xml所在路径
    cd /home/qaperf/jenkinsJacoco
    #ant所在路径,若已配置环境变量执行执行 ant dump即可
    /home/qaperf/jenkinsJacoco/lib/apache-ant-1.9.9/bin/ant dump
    
  3. 构建一栏选择“Invoke Standalone Sonar Analysis”进行sonar插件的配置 其中Project properties的具体配置如下:

# required metadata
#指定唯一key和name
sonar.projectKey=global-online
sonar.projectName=global-online
sonar.projectVersion=1.0

#指定基础路径
sonar.projectBaseDir=/home/qaperf/jenkinsJacoco
#源码路径
sonar.sources=src/global-online/online-war/src/main/java
#class文件路径
sonar.java.binaries=/home/qaperf/haitaoTest/performance/webroot-online-Ins1/WEB-INF/classes

sonar.sourceEncoding=UTF-8

sonar.language=java
#由于只需要展示代码覆盖率,无需静态代码检查,这里为false节省构建时间
sonar.profile=None
sonar.scm.enabled=false
#指定代码覆盖率插件未jacoco
sonar.java.coveragePlugin=jacoco
#指定代码覆盖率二进制文件的路径
sonar.jacoco.reportPath=/home/qaperf/jenkinsJacoco/jacoco.exec

完成以上操作后点击构建,构建完成后就可以去sonar查看结果。


遇到的问题及解决:

问题一: jacoco获取代码覆盖率时需要工程的源码和class文件,工程部署之后应用服务器上只有编译过的class文件,没有源码,需要自动拉取代码,并且我们在实际使用过程中需要代码分支与omad保持一致;
解决方法:与omad代码保持一致可以通过调用omad的api获取相关代码分支,之后git拉取代码,但是git拉代码时需要输入密码,解决方案是将秘钥添加至ssh-agent后可免密登录,参考 http://cobain-li.iteye.com/blog/2318080, 但是经实际使用,仍然会有让输入密码的情况,所以我们可以把添加ssh-agent的过程写入脚本,每次构建先添加一次,这样后续的pull,checkout之类的操作就不需要密码了,如下:

#!/bin/bash
ssh_path=/home/qaperf/.ssh
git_path=/home/qaperf/jenkinsJacoco/src

#use git without password
cd ${ssh_path}
eval "$(ssh-agent -s)"

/usr/bin/expect << EOF
spawn ssh-add /home/qaperf/.ssh/id_rsa
expect "passphrase"
send "****\r" #此处为ssh密码
expect eof
EOF

问题二:Sonar进行覆盖率展示的时候,并不能直接看出代码覆盖率,而是要点开某一个方法后才能看到,操作繁琐;
解决方案:sonar提供了获取代码覆盖率的api,可以将其中类名和覆盖率数值过滤出来,在Jenkins console中打印出来,这样查看就很直观了,也可以加上类方法的sonar链接,可以直接点击查看源码;

/api/measures/component_tree?baseComponentKey=%s&metricKeys=coverage


如何使用代码覆盖率数据

获取到代码覆盖率数据之后,重点是对代码覆盖情况进行分析,根据未覆盖的分支梳理出有哪些场景没有覆盖到,然后对这些场景进行评估,根据重要程度决定是否加入用例集或者是否补测,从而提高用例覆盖度和性能测试的质量,如下图:


总结

目前对代码覆盖率的应用还处于摸索阶段,所以需要继续打开脑洞,从日常测试中寻找可以用代码覆盖率辅助解决的痛点。



网易云产品免费体验馆无套路试用,零成本体验云计算价值。  

本文来自网易实践者社区,经作者牛小宝授权发布