本文将为您提供关于jacoco,检查代码覆盖率的详细介绍,我们还将为您解释jacoco代码覆盖率为0的相关知识,同时,我们还将为您提供关于Android-Jacoco代码覆盖率忽略了Robolectr
本文将为您提供关于jacoco,检查代码覆盖率的详细介绍,我们还将为您解释jacoco代码覆盖率为0的相关知识,同时,我们还将为您提供关于Android-Jacoco代码覆盖率忽略了Robolectric测试、Android-jacoco代码覆盖率:单元测试覆盖率+功能测试覆盖率、ant+Jacoco 统计tomcat远程部署后项目接口自动化测试或者功能测试代码覆盖率、ANT任务:使用JaCoCo的SonarQube扫描仪代码覆盖率报告的实用信息。
本文目录一览:- jacoco,检查代码覆盖率(jacoco代码覆盖率为0)
- Android-Jacoco代码覆盖率忽略了Robolectric测试
- Android-jacoco代码覆盖率:单元测试覆盖率+功能测试覆盖率
- ant+Jacoco 统计tomcat远程部署后项目接口自动化测试或者功能测试代码覆盖率
- ANT任务:使用JaCoCo的SonarQube扫描仪代码覆盖率报告
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测试
试图使用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
完全看到您,但是要在其中包含该标志,您必须:
- 使用 gradle
2.13+
- 使用 雅科
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代码覆盖率:单元测试覆盖率+功能测试覆盖率
参考: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远程部署后项目接口自动化测试或者功能测试代码覆盖率
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扫描仪代码覆盖率报告
在生成XML JaCoCo报告时只需添加以下行
<xml destfile="${sonar.coverage.jacoco.xmlReportPaths}"/>
关于jacoco,检查代码覆盖率和jacoco代码覆盖率为0的介绍现已完结,谢谢您的耐心阅读,如果想了解更多关于Android-Jacoco代码覆盖率忽略了Robolectric测试、Android-jacoco代码覆盖率:单元测试覆盖率+功能测试覆盖率、ant+Jacoco 统计tomcat远程部署后项目接口自动化测试或者功能测试代码覆盖率、ANT任务:使用JaCoCo的SonarQube扫描仪代码覆盖率报告的相关知识,请在本站寻找。
本文标签: