一直以来的工作重心和工作发展都是在移动端上,服务端的东西虽然不能说不会,但是也达不到精通.所以在闲暇的时候也会学习一下服务端的框架和基本知识.
个人认为现在的测试工程师应该是具有多纬度能力和深度学习能力的.比如多维度应该学习不同纬度的技能,如移动端、服务端、自动化框架、内部平台建设、监控体系、精准测试.对多维度技能都入门或者大概了解后,再深挖一个方向去钻研.
本文大致讲述"服务端代码覆盖率统计"的环境搭建和入门,另外也算是最近学习的一个总结.
jacoco 是一个开源的覆盖率工具,通过插桩方式来记录代码执行轨迹.
ant 是构建工具,内置任务和可选任务组成的.Ant 运行时需要一个 XML 文件 (构建文件)。
Spring Boot 是一个轻量级 java web 框架,可以完成基于 Spring 的应用程序的大部分配置工作.
SonarQube 是一个用于管理源代码质量开放平台,它可以从多个维度检测代码质量,可以快速的定位代码中潜在的或者明显的 Bug、错误.
这块的工具对比和相关原理介绍可以参考有赞测试浅谈代码覆盖这篇帖子,原理和工具讲的比较透彻,本文就不做过多介绍了.
启动服务携带 jacocoagent 参数
生成 jacoco.exec
ant 任务生成覆盖率报告
上传到 SonarQube 平台展示
下载地址:https://ant.apache.org/bindownload.cgi
下载完成后并配置 ant 环境变量
vim .bash_profile
export ANT_HOME=/Users/xinxi/Documents/apache-ant-1.9.14
export PATH=${PATH}:${ANT_HOME}/bin
source .bash_profile
输入"ant -version"检查是否安装成功.
build.xml 放到~/Documents/apache-ant-1.9.14/bin 路径下
<?xml version="1.0" encoding="UTF-8"?>
<project name="test" xmlns:jacoco="antlib:org.jacoco.ant" >
<!--Jacoco的安装路径-->
<property name="jacocoantPath" value="/Users/xinxi/Documents/jacoco-0.8.3/lib/jacocoant.jar"/>
<!--最终生成.exec文件的路径,Jacoco就是根据这个文件生成最终的报告的-->
<property name="jacocoexecPath" value="/Users/xinxi/Documents/jacoco-0.8.3/target/jacoco.exec"/>
<!--生成覆盖率报告的路径-->
<property name="reportfolderPath" value="/Users/xinxi/Documents/jacoco-0.8.3/report"/>
<!--远程tomcat服务的ip地址-->
<property name="server_ip" value="127.0.0.1"/>
<!--前面配置的远程tomcat服务打开的端口,要跟上面配置的一样-->
<property name="server_port" value="6300"/>
<!--源代码路径可以包含多个源代码-->
<property name="checkOrderSrcpath" value="/Users/xinxi/Documents/ideaProjcet/springboot-learning-example/springboot-webflux-1-quickstart/src/main/java/" />
<!--.class文件路径可以包含多个-->
<property name="checkOrderClasspath" value="/Users/xinxi/Documents/ideaProjcet/springboot-learning-example/springboot-webflux-1-quickstart/target/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_ip}" reset="true" destfile="${jacocoexecPath}" port="${server_port}" append="false"/>
</target>
<!--jacoco任务:
根据前面配置的源代码路径和.class文件路径,
根据dump后,生成的.exec文件,生成最终的html覆盖率报告。-->
<target name="report">
<delete dir="${reportfolderPath}" />
<mkdir dir="${reportfolderPath}" />
<jacoco:report>
<executiondata>
<file file="${jacocoexecPath}" />
</executiondata>
<structure name="JaCoCo Report">
<group name="Check Order related">
<classfiles>
<fileset dir="${checkOrderClasspath}" />
</classfiles>
<sourcefiles encoding="utf-8">
<fileset dir="${checkOrderSrcpath}" />
</sourcefiles>
</group>
</structure>
<html destdir="${reportfolderPath}" encoding="utf-8" />
</jacoco:report>
</target>
</project>
spring boot 的代码地址:
git clone https://github.com/SuperHulk/springboot-learning-example.git
使用"quickstart"这个项目作为构建服务.
在项目根目录下,执行 mvn package 打包成 jar 包.
官方下载地址
https://www.eclemma.org/jacoco/
javaagent:javaagent 是 JDK 1.5 以后引入的,也可以叫做 Java 代理.
后面跟的参数是 jcocoagent 的 jar 包地址.
includes:包含在执行分析中的类名列表,* 表示全部.
output:表示使用 tcpserver 代理侦听由 address 和 port 属性指定的 TCP 端口,并将执行的数据写入此 TCP 连接,从而实现不停止项目运行实时生成代码覆盖率报告.
port:开启的端口号.
address: 开启的 ip 地址,本地写 127.0.0.1.
jar:运行服务的 jar 包地址.
java -javaagent:/Users/xinxi/Documents/jacoco-0.8.3/lib/jacocoagent.jar=includes=*,output=tcpserver,port=6300,address=127.0.0.1 \
-jar /Users/xinxi/Documents/ideaProjcet/springboot-learning-example/springboot-webflux-1-quickstart/target/springboot-webflux-1-quickstart-0.0.1-SNAPSHOT.jar
测试两个接口的逻辑代码.
curl http://127.0.0.1:8080/hellocity
curl http://127.0.0.1:8080/hellocountry
打开"index.html"报告,展示类的覆盖率文件.
展示类中的代码覆盖范围.
展示类中的代码未覆盖范围.
SonarQube Scanner for Ant 的官方文档.
https://docs.sonarqube.org/display/SCAN/Analyzing+with+SonarQube+Scanner+for+Ant
如果未配置 sonar.java.binaries 会出现如下报错,在 xml 中加入如下配置即可.
org.sonar.squidbridge.api.AnalysisException: Please provide compiled classes of your project with sonar.java.binaries property
增加配置
#添加下面这行
sonar.java.binaries=项目路径/target/classes
<?xml version="1.0" encoding="UTF-8"?>
<project name="My Project" default="all" basedir="/Users/xinxi/Documents/ideaProjcet/springboot-learning-example/springboot-webflux-1-quickstart/" xmlns:sonar="antlib:org.sonar.ant">
<!-- ========= Define the main properties of this project ========= -->
<property name="src.dir" value="src" />
<!-- <property name="test.dir" value="src" /> -->
<property name="lib.junit.dir" value="lib" />
<property name="build.dir" value="target" />
<property name="target.dir" value="target" />
<property name="classes.dir" value="${build.dir}/classes" />
<property name="reports.dir" value="${build.dir}/reports" />
<property name="reports.junit.xml.dir" value="${reports.dir}/junit" />
<!-- Define the Sonar properties -->
<property name="sonar.projectKey" value="jacoco_test" />
<property name="sonar.projectName" value="jacoco test project" />
<property name="sonar.projectVersion" value="1.0" />
<property name="sonar.language" value="java" />
<property name="sonar.sources" value="${src.dir}" />
<!-- <property name="sonar.tests" value="${test.dir}" /> -->
<property name="sonar.binaries" value="${classes.dir}" />
<property name="sonar.java.binaries" value="${classes.dir}" />
<property name="sonar.sourceEncoding" value="UTF-8" />
<property name="sonar.surefire.reportsPath" value="${reports.junit.xml.dir}" />
<!-- The following properties are required to use JaCoCo: -->
<property name="sonar.dynamicAnalysis" value="reuseReports" />
<property name="sonar.java.coveragePlugin" value="jacoco" />
<property name="sonar.jacoco.reportPath" value="/Users/xinxi/Documents/jacoco-0.8.3/target/jacoco.exec" />
<!-- Add your basic Sonar configuration below: sonar.jdbc.url, sonar.jdbc.username, etc. properties -->
<property name="sonar.jdbc.url" value="jdbc:h2:tcp://localhost:9092/sonar" />
<property name="sonar.jdbc.username" value="admin" />
<property name="sonar.jdbc.password" value="admin" />
<!-- ========= Define Sonar target ========= -->
<target name="sonar">
<taskdef uri="antlib:org.sonar.ant" resource="org/sonar/ant/antlib.xml">
<!-- Update the following line, or put the "sonar-ant-task-*.jar" file in your "$HOME/.ant/lib" folder -->
<classpath path="/Users/xinxi/Documents/jacoco-0.8.3/lib/sonarqube-ant-task-2.6.0.1426.jar" />
</taskdef>
<!-- Execute Sonar -->
<sonar:sonar />
</target>
<!-- ========= The main target "all" ========= -->
<target name="all" depends="sonar" />
</project>
执行命令
ant -find sonar.xml 或者 ant sonar
控制台出现"BUILD SUCCESSFUL"说明执行成功
使用 docker 搭建比较简单,启动命令如下.
docker run -d --name sonarqube -p 9000:9000 -p 9092:9092 sonarqube:lts
浏览器打开:0.0.0.0:9000
帐号密码:admin、admin
登录 sonar 查看数据结果,上传 sonar 的意义在于数据汇总,方便多人在线查看数据.
本文仅是简单的介绍了服务端的代码覆盖率统计,其中也包含了多个工具和知识点串联起来.
有赞测试浅谈代码覆盖率
https://testerhome.com/articles/16981?order_by=created_at&
Maven – JaCoCo code coverage example
https://www.mkyong.com/maven/maven-jacoco-code-coverage-example/
spring boot 项目集成 jacoco
http://www.pianshen.com/article/2705317982/
linux 下 jacoco 动态统计覆盖率
https://testerhome.com/topics/5329
https://www.jacoco.org/jacoco/trunk/doc/faq.html
spring boot 项目部署到服务器两种方式
https://blog.csdn.net/qq_22638399/article/details/81506448
ant 官方文档
http://ant.apache.org/manual/index.html
springboot 教程
http://springboot.fun
https://www.jacoco.org/jacoco/trunk/doc/cli.html