GVKun编程网logo

jacoco,检查代码覆盖率(jacoco代码覆盖率为0)

32

本文将为您提供关于jacoco,检查代码覆盖率的详细介绍,我们还将为您解释jacoco代码覆盖率为0的相关知识,同时,我们还将为您提供关于Android-Jacoco代码覆盖率忽略了Robolectr

本文将为您提供关于jacoco,检查代码覆盖率的详细介绍,我们还将为您解释jacoco代码覆盖率为0的相关知识,同时,我们还将为您提供关于Android-Jacoco代码覆盖率忽略了Robolectric测试、Android-jacoco代码覆盖率:单元测试覆盖率+功能测试覆盖率、ant+Jacoco 统计tomcat远程部署后项目接口自动化测试或者功能测试代码覆盖率、ANT任务:使用JaCoCo的SonarQube扫描仪代码覆盖率报告的实用信息。

本文目录一览:

jacoco,检查代码覆盖率(jacoco代码覆盖率为0)

jacoco,检查代码覆盖率(jacoco代码覆盖率为0)

目的:检查代码覆盖率,包括对语句的覆盖,对分支或者条件的覆盖等等

实现原理:1、服务器上采集收据

                  2、采集数据和本地源码做匹配

                  3、浏览器展示匹配结果

使用工具:Sonar5.4:覆盖结果展示;

                 Jacoco7:用于在服务器端产生覆盖数据;

                 命令行方式处理匹配结果;

                 JDK1.8

                 SonarQube Scanner 3.2;

一、服务器环境搭建

1、下载Jacoco并解压上传至服务器(linux)

http://www.eclemma.org/jacoco/index.html

2、在gsxdb.properties文件中加入:指定javaangent的安装位置,指定结果文件jacoco.exec(运行后生成此文件)的位置。

 

 -javaagent:XX/lib/jacocoagent.jar=destfile=XX/jacoco.exec

3、检验是否部署成功:

例gs项目:ps -ef | grep Main_Gs

刷新安装目录,查看是否生成了jacoco.exe文件,如果有此文件,则部署成功。

 

  

4、做功能测试时,需要关闭进程获取结果文件jacoco.exec. 

二、本地环境搭建

1、下载SonarQube并解压到本地。

http://www.sonarqube.org/downloads/ 

2、开启SonarQube:进入本地操作系统对应的目录,如本地操作系统为windows64位,则进入D:\aotu\sonarqube-5.4\bin\windows-x86-64,双击StartSonar.bat启动SonarQube。

3.验证SonarQube是否正常运作:浏览器访问http://localhost:9000/ ,然后登陆,用户名:admin,密码:admin。 

4、进入对应的源码项目,

1)将服务器下载的jacoco.exec,放入目录中

2)新增配置文件:sonar-project.properties,设置项目的参数,供Sonar读取,以及Class文件的地址和结果文件的地址,供Sonar-Scanner读取。

 

 

 

脚本代码参考

# must be unique in a given SonarQube instance
sonar.projectKey=gs
# this is the name displayed in the SonarQube UI
sonar.projectName= gs
#sonar.language=java
sonar.projectVersion=1.0

# Path is relative to the sonar-project.properties file. Replace "\" by "/" on Windows.
# Since SonarQube 4.2, this property is optional if sonar.modules is set.
# If not set, SonarQube starts looking for source code from the directory containing
# the sonar-project.properties file.
sonar.sources=.
#sonar.binaries=C:/Users/Administrator/Desktop/codes/web/yyxw/WebRoot/WEB-INF/classes/com
sonar.java.binaries=项目class文件
# Encoding of the source code. Default is default system encoding
sonar.sourceEncoding=UTF-8

#Set jacoco Configuration
#Code coverage tool
sonar.java.coveragePlugin=jacoco
#Path to the JaCoCo report file containing coverage data by unit tests. The path may be absolute or relative to the project base directory
sonar.jacoco.reportPath=项目路径/jacoco.exec
#Path to the JaCoCo report file containing coverage data by integration tests. The path may be absolute or relative to the project base directory
sonar.jacoco.itReportPath=项目路径/jacoco.exec
#sonar.jacoco.reportMissing.force.zero
sonar.jacoco.reportMissing.force.zero=false

5、下载SonarQube Scanner:Sonar插件,读取sonar-project.properties用于扫描源码,将Jacoco数据结果文件对应到源码中去。SonarScanner最新版本是4.2,但需jdk11了。咱们的环境是jdk8,只能用SonarScanner3.2。

https://docs.sonarqube.org/pages/viewpage.action?pageId=11641634&navigatingVersions=true 

6、安装SonarQube Scanner:将压缩包解压,粘贴复制到SonarQube所在文件夹,将文件合并即可。

 

 

7、将Sonar的bin文件目录加到系统环境变量中

 

 

8、验证环境变量是否加入成功:打开cmd,直接输入sonar-scanner.bat出现图中界面即成功。

9、cmd执行匹配结果

打开项目及sonar-project.properties文件所在目录

cd [项目代码路径],并在此路径下启动sonar,执行sonar-scanner.bat。

 

 

10、注意查看dos界面打印信息,如果有错误信息,具体查看报错原因。

执行完是Excution Success。

 

11、登录http://localhost:9000,打开匹配的项目,不同的颜色对应不同的覆盖程度,颜色越红覆盖得越少,颜色越绿,覆盖得越多,点击不同的版块,可以看到版块内部的覆盖情况。

 

 

 

Android-Jacoco代码覆盖率忽略了Robolectric测试

Android-Jacoco代码覆盖率忽略了Robolectric测试

试图使用Jacoco在Android的Robolectric测试中获得代码覆盖率,但在创建报告时,它只是拒绝承认我的Robolectric测试。

我的jacoco.gradle文件如下:

apply plugin: ''jacoco''jacoco {    toolVersion = "0.7.6.201602180812"}project.afterEvaluate {    android.applicationVariants.all { variant ->        def name = variant.name        def testTaskName = "test${name.capitalize()}UnitTest"        tasks.create(name: "${testTaskName}Coverage", type: JacocoReport, dependsOn: "$testTaskName") {            group = "Reporting"            description = "Generate Jacoco coverage reports for the ${name.capitalize()} build."            classDirectories = fileTree(                    dir: "${project.buildDir}/intermediates/classes/${name}",                    excludes: [''**/R.class'',                               ''**/R$*.class'',                               ''**/*$ViewInjector*.*'',                               ''**/*$ViewBinder*.*'',                               ''**/BuildConfig.*'',                               ''**/Manifest*.*'']            )            sourceDirectories = files([''src/main/java''].plus(android.sourceSets[name].java.srcDirs))            executionData = files("${project.buildDir}/jacoco/${testTaskName}.exec")            reports {                xml.enabled = true                html.enabled = true            }        }    }}

通过此设置,我可以获得“覆盖率”报告,但是尽管在“ src / test / java”中进行了Robolectric测试,但覆盖率为0%。

如果我在该文件中添加以下代码:

android {    testOptions {        unitTests.all {            jacoco {                includeNoLocationClasses = true            }        }    }}

当Gradle尝试同步时,出现以下错误:

错误:没有这样的属性:org.gradle.testing.jacoco.plugins.JacocoTaskExtension_Decorated类的includeNoLocationClasses

我知道我需要Gradle 2.13才能使用此includeNoLocationClasses值,因此在graddle-
wrapper.properties中,我具有以下内容:

#Wed Apr 10 15:27:10 PDT 2013distributionBase=GRADLE_USER_HOMEdistributionPath=wrapper/distszipStoreBase=GRADLE_USER_HOMEzipStorePath=wrapper/distsdistributionUrl=https\://services.gradle.org/distributions-snapshots/gradle-2.13-20160228000026+0000-all.zip

我可以肯定我正在使用Android插件版本1.5运行Gradle 2.13

在我的应用程序Gradle文件中,我具有以下内容:

//...apply from: ''jacoco.gradle''//..testOptions {    unitTests.returnDefaultValues = true}//...debug {    testCoverageEnabled true}

我用来运行coverage的命令是:

./gradlew createDebugCoverageReport

所以我想知道为什么尽管使用了正确的Gradle版本,但仍然出现includeNoLocationClasses错误?除此之外,也许我在Jacoco没有在src
/ test.java中进行Robolectric测试的地方做错了什么?

答案1

小编典典

我没有build.gradle完全看到您,但是要在其中包含该标志,您必须:

  1. 使用 gradle 2.13+
  2. 使用 雅科 0.7.6.201602180812

您确定使用了 gradle 正确版本。因此,我认为问题仅在于使用了错误的 jacoco

提及jacoco {toolVersion = "0.7.6.201602180812"}不会影响 gradle DSL。您应该添加更新的
jacoco 插件:

buildscript {    repositories {        jcenter()    }    dependencies {        classpath ''org.jacoco:org.jacoco.core:...''    }}

并且您应该应用已经在做的插件:

apply from: ''jacoco''

经过这样的配置,您不需要jacoco {toolVersion = "..."}更多。

注意:考虑更新到更新的 android gradle 插件,2.2.x已经很稳定了。 jacoco
也已经有更新的版本0.7.7.201606060606

另外请注意:如果您在Android Studio中看到原始问题,请检查默认情况下是否使用包装器,并确保包装器指向gradle 2.13

Android-jacoco代码覆盖率:单元测试覆盖率+功能测试覆盖率

Android-jacoco代码覆盖率:单元测试覆盖率+功能测试覆盖率

参考:https://docs.gradle.org/current/dsl/org.gradle.testing.jacoco.tasks.JacocoCoverageVerification.html

gradle库下载:https://maven.aliyun.com/mvn/view

案例参考来源:https://www.jianshu.com/p/1a4a81f09526

https://www.jianshu.com/p/1a4a81f09526

其他:https://testerhome.com/topics/8329

 

这几天折腾了很久,主要是现在的案例都是基于gradle3.1.3版本,我不想用旧版本的,查了一些资料,自己改了下代码,可以用了。

前情:

之前听说Android可以用jacoco+monkey做代码覆盖率测试,以前只做过一个spring的jacoco的单元测试覆盖率的demo,没想过Android可以将功能和jacoco联合在一起,这几天很闲就搞了一下。

准备工作:

要有Android项目源码,不用修改项目主体的核心代码,但是需要写一些jacoco的代码,主要是利用instrument在acitivity结束时记录代码覆盖率;

具体内容分两块:

一,Android项目的单元测试代码覆盖率:

利用AndroidStudio自带的task来查看当前AndroidTest文件夹下的单元测试用例覆盖率情况

编辑build.gradle

android {
    ...
    defaultConfig {
         ...
        testInstrumentationRunnerArguments clearPackageData: ''true''
//        执行instrumentation测试时清除缓存
    }
    buildTypes {
        debug {
            testCoverageEnabled = true
            /**打开覆盖率统计开关
             */
        }
    }

  

安装debug包

 

 

执行AndroidTest的覆盖率测试并输出报告

 

 

执行日志是这样的:

  这里摘取的是执行AndroidTest单元测试的片段,通过adb发送instrument命令到手机,执行测试,获取覆盖率数据,并从手机中down下来:

Executing tasks: [createDebugAndroidTestCoverageReport]
...
> Task :app:connectedDebugAndroidTest
...
05:40:39 V/ddms: execute: running am instrument -w -r   -e coverageFile /data/data/com.patech.testApp/coverage.ec -e coverage true -e clearPackageData true com.patech.testApp.test/androidx.test.runner.AndroidJUnitRunner
...
05:40:41 V/InstrumentationResultParser: com.patech.testApp.EspressoTest:
...
05:40:58 V/InstrumentationResultParser: Time: 17.669
05:40:58 V/InstrumentationResultParser: 
05:40:58 V/InstrumentationResultParser: OK (5 tests)
05:40:58 V/InstrumentationResultParser: 
05:40:58 V/InstrumentationResultParser: 
05:40:58 V/InstrumentationResultParser: Generated code coverage data to /data/data/com.patech.testApp/coverage.ec
05:40:58 V/InstrumentationResultParser: INSTRUMENTATION_CODE: -1
...
05:40:59 I/XmlResultReporter: XML test result file generated at D:\androidStudio\MyApplication\app\build\outputs\androidTest-results\connected\TEST-VOG-AL10 - 9-app-.xml. Total tests 5, passed 5, 
05:40:59 V/ddms: execute ''am instrument -w -r   -e coverageFile /data/data/com.patech.testApp/coverage.ec -e coverage true -e clearPackageData true com.patech.testApp.test/androidx.test.runner.AndroidJUnitRunner'' on ''APH0219430006864'' : EOF hit. Read: -1
...
05:40:59 D/com.patech.testApp.coverage.ec: Downloading com.patech.testApp.coverage.ec from device ''APH0219430006864''
...

  

执行完毕后查看build下的reports的详情

 

 

 

二.编写jacoco+instrument的代码,执行功能测试后,在本地生成ec文件,传到pc端后解析成html格式,查看功能测试操作的代码覆盖率执行情况

1.编写FinishListener接口

public interface FinishListener {
    void onActivityFinished();
    void dumpIntermediateCoverage(String filePath);
}

  

编写jacocoInstrumentation方法,实现上面这个接口,网上抄来的,实现了执行完成后生成覆盖率文件并保存到手机本地:

package com.patech.test;

import android.app.Activity;
import android.app.Instrumentation;
import android.content.Intent;
import android.os.Bundle;
import android.os.Looper;
import android.util.Log;

import com.patech.testApp.InstrumentedActivity;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.InvocationTargetException;

public class JacocoInstrumentation extends Instrumentation implements FinishListener{

    public static String TAG = "JacocoInstrumentation:";
    private static String DEFAULT_COVERAGE_FILE_PATH = "/mnt/sdcard/coverage.ec";

    private final Bundle mResults = new Bundle();

    private Intent mIntent;
    //LOGD 调试用布尔
    private static final boolean LOGD = true;

    private boolean mCoverage = true;

    private String mCoverageFilePath;

    public JacocoInstrumentation(){

    }

    @Override
    public void onCreate(Bundle arguments) {
        Log.d(TAG, "onCreate(" + arguments + ")");
        super.onCreate(arguments);
        //DEFAULT_COVERAGE_FILE_PATH = getContext().getFilesDir().getPath() + "/coverage.ec";

        File file = new File(DEFAULT_COVERAGE_FILE_PATH);
        if (!file.exists()) {
            try {
                file.createNewFile();
            }catch (IOException e) {
                Log.d(TAG, "异常 :" + e);
                e.printStackTrace();
            }
        }

        if (arguments != null) {
            mCoverageFilePath = arguments.getString("coverageFile");
        }

        mIntent = new Intent(getTargetContext(), InstrumentedActivity.class);
        mIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        start();
    }

    public void onStart() {
        if (LOGD)
            Log.d(TAG,"onStart()");
        super.onStart();

        Looper.prepare();
/*        InstrumentedActivity activity = (InstrumentedActivity) startActivitySync(mIntent);
        activity.setFinishListener(this);*/
    }

    private boolean getBooleanArgument(Bundle arguments, String tag) {
        String tagString = arguments.getString(tag);
        return tagString != null && Boolean.parseBoolean(tagString);
    }

    private String getCoverageFilePath() {
        if (mCoverageFilePath == null) {
            return DEFAULT_COVERAGE_FILE_PATH;
        }else {
            return mCoverageFilePath;
        }
    }

    private void generateCoverageReport() {
        Log.d(TAG, "generateCoverageReport():" + getCoverageFilePath());
        OutputStream out = null;
        try {
            out = new FileOutputStream(getCoverageFilePath(),false);
            Object agent = Class.forName("org.jacoco.agent.rt.RT")
                    .getMethod("getAgent")
                    .invoke(null);

            out.write((byte[]) agent.getClass().getMethod("getExecutionData",boolean.class)
                    .invoke(agent,false));
        } catch (FileNotFoundException e) {
            Log.d(TAG, e.toString(), e);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } finally {
            if (out != null) {
                try {
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public void UsegenerateCoverageReport() {
        generateCoverageReport();
    }

    private boolean setCoverageFilePath(String filePath){
        if (filePath != null && filePath.length() > 0) {
            mCoverageFilePath = filePath;
        }
        return false;
    }

    private void reportEmmaError(Exception e) {
        reportEmmaError(e);
    }

    private void reportEmmaError(String hint, Exception e) {
        String msg = "Failed to generate emma coverage. " +hint;
        Log.e(TAG, msg, e);
        mResults.putString(Instrumentation.REPORT_KEY_IDENTIFIER,"\nError: " + msg);
    }

    @Override
    public void onActivityFinished() {
        if (LOGD) {
            Log.d(TAG,"onActivityFinished()");
        }
        finish(Activity.RESULT_OK,mResults);
    }

    @Override
    public void dumpIntermediateCoverage(String filePath) {
        if (LOGD) {
            Log.d(TAG,"Intermidate Dump Called with file name :" + filePath);
        }
        if (mCoverage){
            if (!setCoverageFilePath(filePath)) {
                if (LOGD) {
                    Log.d(TAG,"Unable to set the given file path :" +filePath + "as dump target.");
                }
            }
            generateCoverageReport();
            setCoverageFilePath(DEFAULT_COVERAGE_FILE_PATH);
        }
    }
}

  

2.修改AndroidManifest.xml文件,添加往手机读写的权限,以及instrument的设置,该标签与application标签同级:

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <!-- Jacoco权限 -->
    <uses-permission android:name="android.permission.USE_CREDENTIALS" />
    <uses-permission android:name="android.permission.GET_ACCOUNTS" />
    <uses-permission android:name="android.permission.READ_PROFILE" />
    <uses-permission android:name="android.permission.READ_CONTACTS" />

    <instrumentation
        android:name="com.patech.test.JacocoInstrumentation"
        android:handleProfiling="true"
        android:label="CoverageInstrumentation"
        android:targetPackage="com.patech.testApp" />

3.编写jacoco.gradle,用于解析ec,转换成html或者其他格式的报告:

apply plugin: ''jacoco''
//https://docs.gradle.org/current/userguide/jacoco_plugin.html
jacoco {
    toolVersion = "0.8.4"
}
task jacocoTestReport(type: JacocoReport) {
    group = "Reporting"
    description = "Generate Jacoco coverage reports after running tests."
    def debugTree = fileTree(dir: "${buildDir}/intermediates/javac/debug",
//            includes: ["**/*Presenter.*"],
            excludes: [''**/R*.class'',
                       ''**/*$InjectAdapter.class'',
                       ''**/*$ModuleAdapter.class'',
                       ''**/*$ViewInjector*.class''
            ])//指定类文件夹、包含类的规则及排除类的规则,这里我们生成所有Presenter类的测试报告
    def coverageSourceDirs = "${project.projectDir}/src/main/java" //指定源码目录
    def reportDirs="$buildDir/outputs/reports/jacoco/jacocoTestReport"
    reports {
        xml.enabled = true
        html.enabled = true
    }
//    destinationFile=file(reportDirs)
    classDirectories = files(debugTree)
    sourceDirectories = files(coverageSourceDirs)
    executionData = files("$buildDir/outputs/code-coverage/connected/coverage.ec")
}

4.连接手机,安装apk后执行adb语句,通过jacoco开启应用:

adb shell am instrument -w -r  com.patech.testApp/com.patech.testcoverage.test.JacocoInstrumentation

5.可以在手机上开始做功能测试了,测试完毕后导出ec文件:

adb pull mnt/sdcard/coverage.ec C:\Users\user\Desktop\testReport\jacoco

6.将ec文件放入build/outputs/code-coverage/connected下

 

 执行jacocoTestReport的task

 

 在build/reports/jacoco/jacocoTestReport下查看解析的报告

 

查看报告:

 

 

 

 

 

 

  

 

ant+Jacoco 统计tomcat远程部署后项目接口自动化测试或者功能测试代码覆盖率

ant+Jacoco 统计tomcat远程部署后项目接口自动化测试或者功能测试代码覆盖率

 

 

 

1.安装ant 环境,https://ant.apache.org/bindownload.cgi

2.下载jacoco包  https://www.eclemma.org/jacoco/ ,解压后,复制lib下面的jacocoagent.jar  和jacocoant.jar 到tomcat下面的bin目录下面,

   修改catalina.bat文件第一行

set JAVA_OPTS="-javaagent:D:\tomato\bin\jacocoagent.jar=includes=*,output=tcpserver,port=6300,address=127.0.0.1"

address 和port 为下载jacoco.exec文件的请求头

启动tomcat进行测试,

3.创建build.xml文件

<?xml version="1.0" encoding="utf-8"?>
<project name="plate_id_sample_service" xmlns:jacoco="antlib:org.jacoco.ant">
    <taskdef uri="antlib:org.jacoco.ant" resource="org/jacoco/ant/antlib.xml">
        <classpath path="F:\apache-tomcat-8.5.29\bin\jacocoant.jar"/>
    </taskdef>
    
    <target name="dump">
        <!-- address和port和catalina.bat设置保持一致,destfile设置jacoco.exec保存地址 -->
        <jacoco:dump address="127.0.0.1" reset="true" port="6300" destfile="E:\工作\study\jacoco.exec"/>
    </target>
    
    <target name="report">
        <jacoco:report>                        
            <executiondata>
                <file file="E:\工作\study\jacoco.exec"/>
            </executiondata>
                        
            <structure name="pan">
                <!-- 可以按软件功能模块设置多个group,方便在report中查看 -->
                <group name="pan">           
                    <classfiles>
                        <!--.class文件路径,可以放在客户端-->
                        <fileset dir="F:\apache-tomcat-8.5.29\webapps\plan\WEB-INF\classes"/>
                    </classfiles>
                    <sourcefiles encoding="utf-8">
                        <!--源代码路径,可以放在客户端-->
                        <fileset dir="C:\Users\Administrator\Desktop\plan\src\main\java" />
                    </sourcefiles>
                </group>
            </structure>
                     
            <!-- report文件保存地址 -->
            <html destdir="E:\工作\study\jacoco\report"   encoding="utf-8"/>
                        
        </jacoco:report>
    </target>
</project>

4,测试完毕,执行    

ant   dump 后下载

然后执行,ant report

 

 查看测试报告    

 

 

 

可以详细的看到 对应的代码那些路径没有测试到。方便我们进行用例的补充。对我们的接口测试工作,或者手工测试提供一些参考的价值。

这是我手工测试10分钟的覆盖率,看了下里面,很多分支或者代码可能覆盖不到,需要和自动化测试相结合。

 

ANT任务:使用JaCoCo的SonarQube扫描仪代码覆盖率报告

ANT任务:使用JaCoCo的SonarQube扫描仪代码覆盖率报告

在生成XML JaCoCo报告时只需添加以下行

<xml destfile="${sonar.coverage.jacoco.xmlReportPaths}"/>

关于jacoco,检查代码覆盖率jacoco代码覆盖率为0的介绍现已完结,谢谢您的耐心阅读,如果想了解更多关于Android-Jacoco代码覆盖率忽略了Robolectric测试、Android-jacoco代码覆盖率:单元测试覆盖率+功能测试覆盖率、ant+Jacoco 统计tomcat远程部署后项目接口自动化测试或者功能测试代码覆盖率、ANT任务:使用JaCoCo的SonarQube扫描仪代码覆盖率报告的相关知识,请在本站寻找。

本文标签: