android项目的JaCoCo代码覆盖率入门使用
来源:互联网 发布:c语言调用lib 编辑:程序博客网 时间:2024/05/21 23:46
一、项目使用覆盖率初衷
由于公司开发项目业务类型是给企业做定制项目,开发周期短。开发人员在开发过程中往往在将项目提交给测试组测试时,没有进行全面项目测试,导致后面测试组测试出来一堆bug问题,甚至中断测试流程。为了解决大量开发和测试人员的时间,以及检测项目测试的代码是否测试覆盖的程度。在这种条件下,决定使用代码覆盖率来进行查看控制。
二、覆盖率概念
代码覆盖率分析实际上一种度量方式,间接度量质量的方法的过程,是在保证测试质量的时候潜在保证实际产品的质量,在程序中寻找没有被测试用例测试过的地方的流程,创建新的测试用例来增加覆盖率的流程。
代码覆盖分析是一种结构测试技术,属于白盒测试的范畴,结构化测试是以源代码的意图表现为依据来比较被测试程序行为的,与以需求规格为依据去比较被测程序行为的功能测试形成对比,结构化测试检查程序是如何工作的,以及代码结构和逻辑方面的潜在缺陷,而功能测试是不管程序内部是如何运作的,它只检查以及关心程序实现了什么。另外代码覆盖有时被称为“覆盖分析”、“测试覆盖分析”、“测试覆盖”、“覆盖监视器”等。
三、JaCoCo
JaCoCo简述
JaCoCo是一个开源的覆盖率工具(官网地址: http://www.eclemma.org/JaCoCo/ ),它针对的开发语言是java,其使用方法很灵活,可以嵌入到Ant、Maven中;可以作为Eclipse插件,可以使用其JavaAgent技术监控Java程序等等。很多第三方的工具提供了对JaCoCo的集成,如sonar、Jenkins等。
JaCoCo包含了多种尺度的覆盖率计数器,包含指令级覆盖(Instructions,C0coverage),分支(Branches,C1coverage)、圈复杂度(CyclomaticComplexity)、行覆盖(Lines)、方法覆盖(non-abstract methods)、类覆盖(classes),这里就详细介绍不属于入门使用范畴。
四、工程实现覆盖率
在app目录的gradle文件
apply plugin: 'com.android.application'apply plugin: 'jacoco'//添加插件jacocojacoco { toolVersion = "0.7.9"//声明jacoco的版本号}android { compileSdkVersion 25 buildToolsVersion "25.0.2" defaultConfig { applicationId "com.weex.jasso" minSdkVersion 16 targetSdkVersion 25 versionCode 1 versionName "1.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } buildTypes { debug { testCoverageEnabled = true//设置为true } }}dependencies { compile fileTree(include: ['*.jar'], dir: 'libs') androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { exclude group: 'com.android.support', module: 'support-annotations' }) compile 'com.android.support:appcompat-v7:25.1.1' compile 'org.jacoco:org.jacoco.core:0.7.9'//导入jacoco的版本包 compile 'com.android.support.constraint:constraint-layout:+'}def coverageSourceDirs = [ '../app/src/main/java']//建立task任务将outputs/code-coverage/connected/目录下coverage.ec文件的生成覆盖率报告task jacocoTestReport(type: JacocoReport) { group = "Reporting" description = "Generate Jacoco coverage reports after running tests." reports { xml.enabled = true html.enabled = true } classDirectories = fileTree( dir: './build/intermediates/classes/debug', excludes: ['**/R*.class', '**/*$InjectAdapter.class', '**/*$ModuleAdapter.class', '**/*$ViewInjector*.class' ]) sourceDirectories = files(coverageSourceDirs) executionData = files("$buildDir/outputs/code-coverage/connected/coverage.ec") doFirst { new File("$buildDir/intermediates/classes/").eachFileRecurse { file -> if (file.name.contains('$$')) { file.renameTo(file.path.replace('$$', '$')) } } }}
生成代码覆盖率的文件
1. 建立基础类BaseActivity
public abstract class BaseActivity extends Activity { public static String DEFAULT_COVERAGE_FILE_PATH = Environment.getExternalStorageDirectory()+"/hb/oe/"; public static String TAG=Test1Activity.class.getName(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); createFile(DEFAULT_COVERAGE_FILE_PATH,"coverage.ec"); } @Override protected void onDestroy() { super.onDestroy(); closeFile(); } public static void createFile(String path,String fileName){ File file =null; if (path==null){ new Exception("path no null"); } if (fileName==null){ file = new File(path); }else { file=new File(path,fileName); } if (!file.exists()) { try { file.createNewFile(); } catch (IOException e) { e.printStackTrace(); } } public void closeFile(){ OutputStream out = null; try { out = new FileOutputStream(DEFAULT_COVERAGE_FILE_PATH+"/coverage.ec", 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 (Exception e) { Log.d(TAG, e.toString(), e); } finally { if (out != null) { try { out.close(); } catch (IOException e) { e.printStackTrace(); } } } }}
基础类在oncreate()创建coverage.ec文件用于写入代码覆盖率及方法createFile()方法,在界面关闭的onDestroy()生命周期写入覆盖数据方法closeFile();
2. 其他界面的activity继承基础类BaseActivity
这里我为了演示写了Demo,写了两个类Test1Activity 和test2Activity
Test1Activity .class
public class Test1Activity extends BaseActivity { private Button mToastBtn; private Button mRequireBtn; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } public void require(){ Toast.makeText(this,"网络请求",Toast.LENGTH_LONG).show(); } public void toast(){ Intent intent=new Intent(this,Test2Activity.class); startActivity(intent); } public void showTips(View view){ Toast.makeText(this, "我是提示信息", Toast.LENGTH_SHORT).show(); } public void showError(View view){ Toast.makeText(this,"我正在抛出错误",Toast.LENGTH_SHORT).show(); startActivity(new Intent(this,Test2Activity.class)); finish(); } public void showTest(){ Toast.makeText(this,"测试",Toast.LENGTH_SHORT).show(); }}
Test2Activity.class
public class Test2Activity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main2); }}
在Test1Activity写了两个按钮点击事件,用于明确区别事件点击覆盖率;
3. 直接app运行到手机端
4. 生成报告
将手机中的coverage.ec文件(上述代码有具体路径,可以自行日记打印出来,沿着相对路径去找)复制到build/outputs/code-coverage/connected下
5.生成报表的gradle指令
gradlew jacocoTestReport
还记得在gradle创建的task任务叫jacocoTestReport,就是将coverage.ec生成报表文件可视化。
五、报告分析
报表在build/reports/jacoco/jacocoTestReport/html下,右击查找index.html点击打开。
如上图所示,标记绿色的为分支覆盖充分,标记黄色的为部分分支覆盖(上图没有),标红色的为未执行该分支;
Demo的下载
小红的测试生涯 http://www.dzwanli.com.cn/?p=1374
使用 Jacoco 实现 Android 端手工测试覆盖率统计 https://testerhome.com/topics/8554
- android项目的JaCoCo代码覆盖率入门使用
- 实用Jacoco代码覆盖率Android集成与使用
- Android UI测试框架Espresso以及代码覆盖率jacoco的使用
- 使用MAVEN+Jacoco统计单元测试的代码覆盖率
- Jacoco 代码覆盖率,监控WEB项目
- Jacoco动态监测Web项目的覆盖率
- 代码覆盖率-JaCoCo
- Jacoco覆盖率工具使用
- 【android测试】jacoco做功能测试代码覆盖率统计
- 使用dropwizard(4)-加入测试-jacoco代码覆盖率
- AndroidStudio中使用Jacoco统计Android应用程序代码覆盖率
- Jacoco覆盖率工具使用调研
- jacoco统计自动化测试代码覆盖率
- java代码覆盖率工具-Emma和Jacoco
- Java单元测试之代码覆盖率-JaCoCo
- JAVA代码覆盖率工具JaCoCo-实践篇
- JAVA代码覆盖率工具JaCoCo-踩坑篇
- sonar 集成代码测试覆盖率插件jacoco
- Git-Gui的中文乱码解决方法
- socket 设备自动重启/断电 recv send阻塞的解决办法
- 前端获取到后端数据后,要根据数据类型传输不同的属性值到后端,后端完成特殊业务处理
- Weex新建项目报错weex-vue-render/index.js
- java 给线程池改名字的作用
- android项目的JaCoCo代码覆盖率入门使用
- py-faster-rcnn_cuda8.0_cudnn5.0_报错
- cvNamedWindow与namedWindow,cvShowImage与inshow的区别
- LeetCode
- tcpdf导入官方示例报错解决方案
- Java 自动识别对象属性有无改变
- UICollectionView创建头部headerview
- android studio 编译C生成.so文件
- SpringMVC的几种返回方式