SonarQube +Jenkins +JaCoCo 实现Java单元测试,单节点集成覆盖率测试,集群集成覆盖率测试(三)~集成测试篇

3 篇文章 2 订阅
2 篇文章 1 订阅

写在最前:

本文主要讲解SonarQube实现对Java代码的集成覆盖率扫描,代码质量扫描。
其中,集成覆盖率分为单节点,集群两种模式,文内都有详解。

参考链接:

环境版本和安装

SonarQube单元测试覆盖率详解

流程说明

本篇内容实际为4-7步,1-3步骤配置可以参考Jenkins发布配置
在这里插入图片描述

  1. Jenkins拉取被测项目,编译打包,发送到服务器并启动,此处在应用服务器JVM中添加了JacocoAgent,动态获取覆盖率
  2. Jenkins拉取被测代码和测试代码
    被测代码:扫描java代码,扫描代码质量;扫描class类,和Ant获取到的覆盖代码行进行对比,生成覆盖率文件(能在SonarQube上展示覆盖率和每个代码文件的详细覆盖率)
    测试代码:执行测试类,通过Ant获取覆盖率文件
  3. Ant
    获取覆盖率文件,整合覆盖率文件(集群模式),生成xml报告(新版本SonarQube推荐扫描xml报告生成页面展示内容而不是直接获取到的原始覆盖率文件)
  4. SonarScanner
    扫描被测项目,获取代码质量报告
    扫描Ant覆盖率报告:获取详细覆盖率结果,和扫描class类结合使用
    扫描class文件,生成SonarQube覆盖率索引(如果不扫描只能看到一个覆盖率,扫描之后能看详细每个文件,每行覆盖了多少)

应用服务器配置

1. 安装Jacoco
在被测应用服务器上需要安装JaCoCo,参考环境版本和安装,直接将整个jacoco文件夹复制到应用服务器即可
2. 修改应用启动参数
项目启动jvm 参数中添加:注:下面参数必须添加在jvm参数最前面,否则可能不生效
-javaagent:jacocoagent.jar=includes=*,output=tcpserver,address=项目服务器本机ip,port=自定义端口,append=false

并且pom中不能配置跳过test,否则单元测试类不执行
在这里插入图片描述

分布式单节点环境覆盖率扫描配置

1. 被测项目(需要扫描的项目)配置
pom.xml 同级目录下添加sonar-project.properties文件, 内容如下:

#sonarqube key
sonar.projectKey=ncba_interface_account
#sonarqube ui job name
sonar.projectName=ncba_interface_account
#sonarqube job version
sonar.projectVersion=1.0.0
#more than one branch , set branch name
#sonar.branch.name=account-develop
#code language
sonar.language=java
#exclusion code file
#**/entity/**,*/*BO.java,
sonar.exclusions=**/service/detailedness/**,**/service/accounting/**,**/service/account/**,**/action/wallettransaction/**,**/action/saaquery/**
#more than one moudle,set this
#模块名,多个模块就配置多个,如果就一个可以省略
sonar.modules=account-api,account-web
#↓↓↓这个是目录名,对应↑↑↑↑↑,这里是模块↓↓↓↓↓↓↓代码路径
account-api.sonar.projectBaseDir=account-api
account-web.sonar.projectBaseDir=account-web
#code file path
sonar.sources=src/main/java
sonar.tests=src/test/java
sonar.sourceEncoding=UTF-8
sonar.java.binaries=target/classes
#SonarQube username and password
sonar.login=user
sonar.password=password
#jacoco config
sonar.java.coveragePlugin=jacoco
#report file path
#这个路径是覆盖率文件生成覆盖率报告的位置,这个位置是用于本配置文件去读取的
sonar.coverage.jacoco.xmlReportPaths=/home/jenkins/interface_test/account/report.xml

git路径演示:
在这里插入图片描述
2. 测试项目配置

测试项目需要添加build.xml,是一个ant build文件,负责获取到远程覆盖率,并且在本地生成覆盖率文件,导出覆盖率报告,供上面配置的sonarqube读取。

build.xml 内容如下:

<?xml version="1.0" encoding="UTF-8" ?>
<project name="testCodeCoverage" xmlns:jacoco="antlib:org.jacoco.ant" default="run" ><!--默认执行run方法-->

    <property name="result.exec.file" location="/home/jenkins/interface_test/account/jacocoremote_account.exec"/><!--存放覆盖率文件的位置-->
    <property name="reportfolderPath" value="/home/jenkins/interface_test/account"/> <!--生成覆盖率报告的路径-->
    <property name="result.jar.file" location="/home/jenkins/jacoco/lib/jacocoant.jar"/><!--指定的jacocoant.jar所在位置-->
    <property name="result.exec.ip" value="192.168.0.1"/><!--部署被测项目的服务器ip-->
    <property name="result.exec.port" value="40007"/><!--部署被测服务器开发的jacoco端口,ip和端口对应应用jvm启动参数的jacoco ip和端口-->
    <!--此处取的jenkins workspace总路径,多余文件在下面排除-->
    <property name="Model1JavaPath" value="/var/lib/jenkins/workspace/interface_test/account"/>  <!--java代码-->
    <property name="Model1ClassPath" value="/var/lib/jenkins/workspace/interface_test/account"/>  <!--class代码-->

    <taskdef uri="antlib:org.jacoco.ant" resource="org/jacoco/ant/antlib.xml">
        <classpath path="${jacoco.jar.file}"/>
    </taskdef>

    <target name="run"><!--设置总体调度器-->
        <echo message="start..."/>
        <echo message="dump..."/>
        <antcall target="dump"/>
        <echo message="report..."/>
        <antcall target="report"/>
    </target>
    <!--生成覆盖率二进制文件-->
    <target name="dump">
     <!--删除历史报告-->
        <delete dir="${reportfolderPath}" />
        <mkdir dir="${reportfolderPath}" />
        <jacoco:dump address="${result.exec.ip}" reset="false" destfile="${result.exec.file}" port="${result.exec.port}" append="flase"/>
    </target>
    <!--生成报告-->
    <target name="report">
        <jacoco:report>
            <executiondata>
                <!--jacoco.exec二进制文件位置-->
                <file file="${result.exec.file}"/>
            </executiondata>
            <structure name="JaCoCo Report">
                <!--api-->
              <!--  <group name="account-api">
                    <sourcefiles encoding="UTF-8">
                        <fileset dir="${Model1ClassPath}/account-api/src/main/java">
                            <exclude name="*/*BO.java"/>
                            <exclude name="**/model/**"/>
                            <exclude name="**/Application.java"/>
                            <exclude name="**/entity/**"/>
                            <exclude name="**/dal/**"/>
                            <exclude name="**/common/**"/>
                            <exclude name="**/test_project/**"/>
                        </fileset>

                    </sourcefiles>
                    <classfiles>
                        <fileset dir="${Model1JavaPath}/account-api/target/classes"/>
                    </classfiles>
                </group>-->
                <!--web-->
                <group name="account-web">
                    <sourcefiles encoding="UTF-8">
                        <fileset dir="${Model1JavaPath}/account-web/src/main/java">
                            <exclude name="*/*BO.java"/>
                            <exclude name="**/model/**"/>
                            <exclude name="**/Application.java"/>
                            <exclude name="**/entity/**"/>
                            <exclude name="**/dal/**"/>
                            <exclude name="**/common/**"/>
                            <exclude name="**/test_project/**"/>
                        </fileset>

                    </sourcefiles>
                    <classfiles>
                        <fileset dir="${Model1ClassPath}/WEB-INF/classes"/>
                    </classfiles>
                </group>
            </structure>
            <!--生成报告格式,html,csv,xml-->
            <html destdir="${reportfolderPath}" encoding="utf-8"/>
            <csv destfile="${reportfolderPath}/report.csv"/>
            <xml destfile="${reportfolderPath}/report.xml"/>
        </jacoco:report>
    </target>
</project>

3. Jenkins 配置
关键配置 :
在这里插入图片描述
在这里插入图片描述
上面几步基本都是固定写法,不用动
在这里插入图片描述
重点说明:

说明1. 我将覆盖率文件存在了/home/jenkins 目录下,jenkins workspace 只支持相对路径,娶不到 覆盖率文件,所以软连接过来

说明2. 将打好的war包移动到workspace根下并解压,该操作为必须,多次测试发现,如果不用mvn package打包,只用mvn compline ,实际上在jacoco 上,他会认为 编译方式所生成的classes文件的classID不相同,认为是不同的class文件,简单来说,就是覆盖率结果为0(部分情况可能不为0,因为有mvn私服模块是提前打包,可能打包方式相同,不理解的忽略这段话)

说明3. 此处是用于自动导出美化后的测试结果文件,暂时忽略

其他说明. 如果项目有单测,集群集成测试,单节点集成测试
sonar扫描配置文件起名请不要用sonar-project.properties
因为jenkins如果有叫sonar-project.properties的文件,直接就使用这个文件,即便配置了其他文件名也不好使

效果图:图中显示错误是 代码问题,忽略在这里插入图片描述

分布式集群环境下覆盖率扫描配置

和单节点相比,不同的点就是涉及到服务分发,那么覆盖率分散的问题,我们需要做的就是覆盖率整合。

应用服务器配置

配置和上面无变化

sonar-project.properties文件配置

只改了下覆盖率文件路径
#sonarqube key
sonar.projectKey=ncba_interface_account
#sonarqube ui job name
sonar.projectName=ncba_interface_account
#sonarqube job version
sonar.projectVersion=1.0.0
#more than one branch , set branch name
#sonar.branch.name=account-develop
#code language
sonar.language=java
#exclusion code file
#**/entity/**,*/*BO.java,
sonar.exclusions=**/service/detailedness/**,**/service/accounting/**,**/service/account/**,**/action/wallettransaction/**,**/action/saaquery/**
#more than one moudle,set this
sonar.modules=account-api,account-web
account-api.sonar.projectBaseDir=account-api
account-web.sonar.projectBaseDir=account-web
#code file path
sonar.sources=src/main/java
sonar.tests=src/test/java
sonar.sourceEncoding=UTF-8
sonar.java.binaries=target/classes
#SonarQube username and password
sonar.login=user
sonar.password=password
#jacoco config
sonar.java.coveragePlugin=jacoco
#report file path
sonar.coverage.jacoco.xmlReportPaths=/home/jenkins/interface_test/app/acm/report.xml

build.xml 文件配置

以三节点为例
<?xml version="1.0" encoding="UTF-8" ?>
<project name="testCodeCoverage" xmlns:jacoco="antlib:org.jacoco.ant" default="run" ><!--默认执行run方法-->
    <property name="result.exec.file.dir" location="/home/jenkins/interface_test/account/"/><!--存放临时覆盖率文件的位置-->
    <property name="result.exec.file1" location="/home/jenkins/interface_test/account/jacocoremote_account.exec1"/><!--存放临时覆盖率文件的位置-->
    <property name="result.exec.file2" location="/home/jenkins/interface_test/account/jacocoremote_account.exec2"/><!--存放临时覆盖率文件的位置-->
    <property name="result.exec.file3" location="/home/jenkins/interface_test/account/jacocoremote_account.exec3"/><!--存放临时覆盖率文件的位置-->
    <property name="result.exec.file" location="jacocoremote_account.exec"/><!--存放最终覆盖率文件的位置-->
    <property name="reportfolderPath" value="/home/jenkins/interface_test/app/acm"/> <!--生成覆盖率报告的路径-->
    <property name="result.jar.file" location="/home/jenkins/jacoco/lib/jacocoant.jar"/><!--指定的jacocoant.jar所在位置-->
    <property name="result.exec.ip1" value="192.168.1.1"/><!--部署被测项目的服务器ip-->
    <property name="result.exec.ip2" value="192.168.1.2"/><!--部署被测项目的服务器ip-->
    <property name="result.exec.ip3" value="192.168.1.3"/><!--部署被测项目的服务器ip-->
    <property name="result.exec.port" value="40007"/><!--部署被测服务器开发的jacoco端口-->
    <!--此处取的jenkinsworkspace总路径,多余文件在下面排除-->
    <property name="Model1JavaPath" value="/var/lib/jenkins/workspace/interface_test/account"/>  <!--模块1java代码-->
    <property name="Model1ClassPath" value="/var/lib/jenkins/workspace/interface_test/account"/>  <!--模块1class代码-->

    <taskdef uri="antlib:org.jacoco.ant" resource="org/jacoco/ant/antlib.xml">
        <classpath path="${jacoco.jar.file}"/>
    </taskdef>

    <target name="run"><!--设置总体调度器-->
        <echo message="start..."/>
        <echo message="dump1..."/>
        <antcall target="dump1"/>
        <echo message="dump2..."/>
        <antcall target="dump2"/>
        <echo message="dump3..."/>
        <antcall target="dump3"/>
        <echo message="merge..."/>
        <antcall target="merge"/>
        <echo message="report..."/>
        <antcall target="report"/>
    </target>
    <!--生成覆盖率二进制文件-->
    <target name="dump1">
        <delete dir="${reportfolderPath}" />
        <mkdir dir="${reportfolderPath}" />
        <jacoco:dump address="${result.exec.ip1}" reset="false" destfile="${result.exec.file1}" port="${result.exec.port}" append="flase"/>
    </target>
    <target name="dump2">
        <jacoco:dump address="${result.exec.ip2}" reset="false" destfile="${result.exec.file2}" port="${result.exec.port}" append="flase"/>
    </target>
    <target name="dump3">

        <jacoco:dump address="${result.exec.ip3}" reset="false" destfile="${result.exec.file3}" port="${result.exec.port}" append="flase"/>
    </target>
    <!--合并覆盖率文件-->
    <target name="merge">
        <jacoco:merge destfile="${result.exec.file}">
            <fileset dir="${result.exec.file.dir}" includes="**/*.exec*"/>
        </jacoco:merge>
    </target>
    <!--生成报告-->
    <target name="report">
        <!--删除历史报告-->

        <jacoco:report>
            <executiondata>
                <!--jacoco.exec二进制文件位置-->
                <file file="${result.exec.file}"/>
            </executiondata>
            <structure name="JaCoCo Report">
                <!--web-->
                <group name="account-web">
                    <sourcefiles encoding="UTF-8">
                        <fileset dir="${Model1JavaPath}/account-web/src/main/java">
                            <exclude name="*/*BO.java"/>
                            <exclude name="**/model/**"/>
                            <exclude name="**/Application.java"/>
                            <exclude name="**/entity/**"/>
                            <exclude name="**/dal/**"/>
                            <exclude name="**/common/**"/>
                            <exclude name="**/test_project/**"/>
                        </fileset>

                    </sourcefiles>
                    <classfiles>
                        <fileset dir="${Model1ClassPath}/WEB-INF/classes"/>
                    </classfiles>
                </group>
            </structure>
            <!--生成报告格式,html,csv,xml-->
            <html destdir="${reportfolderPath}" encoding="utf-8"/>
            <csv destfile="${reportfolderPath}/report.csv"/>
            <xml destfile="${reportfolderPath}/report.xml"/>
        </jacoco:report>
    </target>
</project>

jenkins配置

只需要更改这一步,其他完全不变

在这里插入图片描述

OK,大功告成!

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值