相关准备

项目测试准备

SpringBoot项目:

  1. SpringBoot项目地址:https://github.com/jinglv/spring-boot-restful-api.git
  2. SpringBoot项目,编写项目相关单元测试用例

SonarQube平台

详见:SonarQube平台介绍 一篇,介绍SonarQube平台如何搭建

Java测试报告与覆盖率

官网各语言分析:https://docs.sonarqube.org/latest/analysis/coverage/

Property Scope Example Description
sonar.junit.reportPaths Project-wide target/surefire-reports,myModule/target/surefire-reports Import tests execution reports(Surefire XML format).
Set the property with a list of comma-separated paths to the directories containing the XML reports.
sonar.jacoco.reportPaths Project-wide target/jacoco.exec,target/jacoco-it.exec(default) Import JaCOCO code coverage reports.
Set the property to the path of the JaCOCO.exec reports,merge multiple reports.
(if you are using a version of SonarQube prior to 6.2 please use sonar.jacoco.reportPath proerty)

Java单元测试用Sonar执行

获取结果

  1. 进入项目工程下,进行单元测试

    1
    jingdeMacBook-Pro:spring-boot-restful-api apple$ mvn clean test
  1. 将测试结果上传到SonarQube平台

    1
    2
    3
    4
    5
    6
    7
    jingdeMacBook-Pro:spring-boot-restful-api apple$ mvn sonar:sonar   \
    -Dsonar.host.url=http://60.205.228.49:9000/ \
    -Dsonar.login=053ed1077e82a2bb36eebf619d24d75b8c5738b9 \
    -Dsonar.ws.timeout=300 \
    -Dmaven.test.skip=false \
    -Dsonar.junit.reportPaths='./target/surefire-reports'

    • -Dsonar.junit.reportPaths:上传执行的测试报告
  2. 查看执行结果

    image-20210301153330162

  3. SonarQube平台上,查看结果

    image-20210301153630063

分析结果

Sonar的官方文档中对各项指标有详细的描述,具体讲解可见官方文档。

查看Measures(度量)界面

image-20210301153930633

等级A、B、C、D、E,从不同的维度进行等级打分,则看图很清楚的看到代码质量的好坏

通用测试数据导入

官方文档介绍:https://docs.sonarqube.org/latest/analysis/generic-test/

通⽤测试数据Generic Test Data

  • 通⽤覆盖率数据: sonar.coverageReportPaths
  • 通⽤测试执⾏数据: sonar.testExecutionReportPaths

sonar.testExecutionReportPaths

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<testExecutions version="1">
<file path="testx/ClassOneTest.xoo">
<testCase name"test1" duration="5" />
<testCase name"test2" duration="500">
<skipped message="short message">other</skipped>
</testCase>
<testCase name"test3" duration="100">
<failure message="short">stacktrace</failure>
</testCase>
<testCase name"test4" duration="500">
<error message="short">stacktrace</error>
</testCase>
</file>
</testExecutions>

sonar.coverageReportPaths

1
2
3
4
5
6
7
8
9
<coverage version="1">
<file path="xoucres/hello/NoConditions.xoo">
<lineToCover lineNumber="6" covered="true" />
<lineToCover lineNumber="7" covered="false" />
</file>
<file path="xoucres/hello/WithConditions.xoo">
<lineToCover lineNumber="3" covered="true" branchesToCover="2" coveredBranches="1" />
</file>
</coverage>

通用测试的用途

  • 合并覆盖率,转换为通用覆盖率数据
  • 把其他工具的覆盖率转化过来
  • 把git diff的代码映射多来

演示

  1. 本地创建一个目录

    1
    jingdeMacBook-Pro:JavaProject apple$ mkdir testdata
  1. sonar.testExecutionReportPaths中的示例,复制到一个xml文件中

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    jingdeMacBook-Pro:JavaProject apple$ vim generic_test.xml
    jingdeMacBook-Pro:JavaProject apple$ cat generic_test.xml
    <testExecutions version="1">
    <file path="testx/ClassOneTest.xoo">
    <testCase name="test1" duration="5"/>
    <testCase name="test2" duration="500">
    <skipped message="short message">other</skipped>
    </testCase>
    <testCase name="test3" duration="100">
    <failure message="short">stacktrace</failure>
    </testCase>
    <testCase name="test4" duration="500">
    <error message="short">stacktrace</error>
    </testCase>
    </file>
    </testExecutions>

    注意:里面的file要对应的已有的文件路径

  2. 使用sonar-scanner工具,扫描传到SonarQube服务上

    1
    jingdeMacBook-Pro:JavaProject apple$ sonar-scanner -Dsonar.testExecutionReportPaths=testdata/generic_test.xml -Dsonar.projectKey=generic-test -Dsonar.projectName=generic-test -Dsonar.sources=./spring-boot-restful-api/ -Dsonar.java.binaries=./spring-boot-restful-api/target/

    这种方式就适合多语言的测试用例上传

覆盖率统计

覆盖率统计的⼯具

  • emma
  • cobertura
  • jacoco

目前最流行的覆盖率统计工具是jacoco,具体详情介绍请看JaCOCO介绍

Jacoco的底层技术

image-20210301171312036

字节码插桩

  • ASM:所有字节码插桩框架的底层,性能最高,apm框架的核心基础
  • JavaAssist:简单易用
  • ByteBuddy、 BTrace、 JVM-Sandbox。。。

覆盖率统计原理

image-20210301171357157

  • 对JVM的字节码插桩
  • 基于block插桩
  • 计算覆盖的代码块

jacoco使用

jacoco官方文档:https://www.jacoco.org/jacoco/trunk/doc/index.html

根据官方文档说明,执行命令,获取帮助文档:mvn help:describe -Dplugin=org.jacoco:jacoco-maven-plugin -Ddetail

1
2
# 进入工程目录下执行
jingdeMacBook-Pro:spring-boot-restful-api apple$ mvn help:describe -Dplugin=org.jacoco:jacoco-maven-plugin -Ddetail

命令行执行,jacoco分析及获得测试报告

1
jingdeMacBook-Pro:spring-boot-restful-api apple$ mvn clean org.jacoco:jacoco-maven-plugin:0.8.5:prepare-agent test org.jacoco:jacoco-maven-plugin:0.8.5:report -Dmaven.test.failure.ignore=true -Dmaven.test.skip=false

也可基于Maven项目的pom.xml文件中添加

进入到项目目录下,target/site/jacoco目录下,打开index.html文件查看测试覆盖率报告

image-20210301180427789之后,我们将测试覆盖率报告上传到SonarQube平台,通过SonarQube进行测试结果的分析

1
jingdeMacBook-Pro:spring-boot-restful-api apple$ mvn sonar:sonar -Dsonar.host.url=http://xx.xxx.xxx.xx:9000/ -Dsonar.login=053ed1077e82a2bb36eebf619d24d75b8c5738b9 -Dsonar.ws.timeout=300

查看前面的SonarQube平台,我们看到覆盖率的值为0.00%,我们己经将jacoco的覆盖率报告已上传,这是查看SonarQube平台的结果

image-20210301181132473

也可以使用sonar-scanner进行测试报告的上传SonarQube

1
2
3
4
5
6
7
8
9
10
SONARQUBE_HOST=http://xxx.xxx.xxx.xxx:9000 
sonar-scanner \
-Dsonar.host.url=$SONARQUBE_HOST \
-Dsonar.login=$SONARQUBE_TOKEN \
-Dsonar.projectKey=$projectKey \
-Dsonar.projectName=$projectName \
-Dsonar.sources=$(echo **/src | sed 's# #,#g') \
-Dsonar.java.binaries="**/target" \
-Dsonar.junit.reportPaths=$(find . -name "surefire-reports" | xargs | sed 's# #,#g') \
-Dsonar.coverage.jacoco.xmlReportPaths="**/jacoco/jacoco.xml"

通用覆盖率数据导入SonarQube

img