Jenkins构建Android项目持续集成之单元测试及代码覆盖率
单元测试
在软件开发中一直在推崇TDD(测试驱动开发),但是一直不能被有效的执行或者并不是真正的测试驱动开发(先开发后写单元测试),因为我们懒!而Android开发又是大多应用层面的开发,很多都是和视图层紧密相连的,业务逻辑和view相绑定,这导致编写单元测试有相当大的困难,因此就我项目而言,只针对工具类、服务端API编写单元测试。关于android Studio如何编写单元测试并运行,可以看之前写的一篇文章Android Studio 单元测试
代码覆盖率
编写好单元测试后,我们需要知道,测试用例是否覆盖了代码的所有分支情况,这样才能保证代码的可靠性、正确性。
编写测试用例
如果使用Android Studio创建项目的话,那么默认的会在androidTest包下生成一个ApplicationTest类,在这里面可以写测试用例。
上图写的是一个SharedPreferences Util工具类的测试用例。
如果你的测试用例不想写在这个包下,想自定义,也可以在项目的build.gradle写如下的配置
android {
sourceSets {
androidTest{
java.srcDirs = ['src/com/helen/andbase/tests']
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 1
- 2
- 3
- 4
- 5
- 6
Gradle配置jacoco
Jacoco是一个开源的覆盖率工具。这里讲下gradle如何配置。
首先要在项目的build.gradle引入插件,语句如下:
apply plugin: 'jacoco'
- 1
- 1
然后注明使用的版本号
jacoco{
version "0.7.4.201502262128"
}
- 1
- 2
- 3
- 1
- 2
- 3
接着,申明一个gradle task
task jacocoTestReport(type:JacocoReport,dependsOn:"connectedAndroidTest"){
group = "Reporting"
description = "Generate Jacoco coverage reports after running tests."
reports{
xml.enabled = false
html.enabled = true
csv.enabled = false
}
classDirectories = fileTree(
dir : "$buildDir/intermediates/classes/debug",
excludes : [
'**/*Test.class',
'**/R.class',
'**/R$*.class',
'**/BuildConfig.*',
'**/Manifest*.*'
]
)
def coverageSourceDirs = ['src/main/java']
additionalSourceDirs = files(coverageSourceDirs)
sourceDirectories = files(coverageSourceDirs)
additionalClassDirs = files(coverageSourceDirs)
executionData = files("$buildDir/outputs/code-coverage/connected/coverage.ec")
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
最后,打开testCoverageEnabled,需要注意的是,打开该属性的话,在断点调试的时候会导致方法参数值丢失(看不到),所以在调试的时候要记得把它关掉。
buildTypes {
debug{
testCoverageEnabled true
}
}
- 1
- 2
- 3
- 4
- 5
- 1
- 2
- 3
- 4
- 5
完整的gradle配置如下
apply plugin: 'com.android.library'
//代码覆盖率插件
apply plugin: 'jacoco'
android {
compileSdkVersion 22
buildToolsVersion '22.0.1'
defaultConfig {
minSdkVersion 8
targetSdkVersion 22
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
debug{
testCoverageEnabled true
}
}
lintOptions {
abortOnError false
}
packagingOptions {
exclude 'META-INF/NOTICE'
exclude 'META-INF/LICENSE'
}
jacoco{
version "0.7.4.201502262128"
}
}
//jacocoTestReport依赖于connectedAndroidTest task,所以在执行jacoco之前需要先执行connectedAndroidTest,也就是说需要连接测试机(模拟器or真机)
task jacocoTestReport(type:JacocoReport,dependsOn:"connectedAndroidTest"){
group = "Reporting"
description = "Generate Jacoco coverage reports after running tests."
reports{
xml.enabled = false
html.enabled = true
csv.enabled = false
}
classDirectories = fileTree(
dir : "$buildDir/intermediates/classes/debug",
excludes : [
'**/*Test.class',
'**/R.class',
'**/R$*.class',
'**/BuildConfig.*',
'**/Manifest*.*'
]
)
def coverageSourceDirs = ['src/main/java']
additionalSourceDirs = files(coverageSourceDirs)
sourceDirectories = files(coverageSourceDirs)
additionalClassDirs = files(coverageSourceDirs)
executionData = files("$buildDir/outputs/code-coverage/connected/coverage.ec")
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:22.2.1'
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
生成报告
配置完上面的步骤之后,打开Terminal,并输入命令gradlew jacocoTestReport,回车执行。
之后打开下面的地址,先看下测试结果
从上图,可以看到有些测试用例是没有跑通的,点击之后可以看详情信息
根据提示信息,修改代码,直到测试用例跑通之后,如下图:
然后打开下面的地址,如果测试用例没有全部跑通的话,就不会生成代码覆盖率报告。
我们去查看下,之前跑的测试用例的覆盖率情况
再点击进去的话,可以看到具体有哪些分支路径是没有覆盖到的。
将报告通过邮箱发送给相关人员
通过上面的步骤,我们已经可以看到了结果报告,但是,我们的主题是持续集成&自动化,所以,还没有全部完成,我们的主角依然是jenkins。所以,接下来要讲的是:通过jenkins项目配置,让程序自动生成报告,并将结果通过邮件发送给相关人员。
先后会创建“Publish JUnit test result report”、”Record JaCoCo coverage report “、“Publish Android Lint results”。
配置单元测试报告
这时候,报了个错误,说当前路径没有匹配到文件,没关系,因为我们还没有执行命令之前,一些文件夹还没有生成,所以可以先忽略。
配置代码覆盖率报告
主要的几个参数配置,“Path to class directories”配置的是编译后.class文件的路径地址,Android都是放在build路径下build\intermediates\classes;“Path to source directories”配置的是Java代码路径。
配置Android Lint报告
Android Lint是Android自带的一个功能,它可以检测一些不规范的写法,并提示。该功能gradle不用配置任何东西,只要执行build之后就会自动生成报告。
上图中不用填写入任何路径,默认的即可。
邮件配置及gradle执行命令的修改
首先,我们先修改下邮件的发送内容。
我们在上一节的基础上,只是新增加了以上3中报告的地址。
接着,还需要修改gradle 执行的命令。
项目的build.gradle修改下
去掉connectedAndroidTest的关联,因为我们已经独立使用命令执行connectedAndroidTest了,所以jenkins服务器在跑job的时候,请确保已经打开了Android模拟器,否则会出错。
查看邮件报告
配置完以上的步骤之后,将代码push到github上,等待jenkins触发构建或者我们手动执行构建都可以。
邮件里增加了配置里相应修改的内容。
注意:因为我的项目是一个lib项目,而在Android里lib项目生成的jar包是一个aar,所以这里的单元测试,我是写在lib项目里,然后构建产物,我也修改为获取aar包,修改如下:
总结
跟着上面的步骤来,我们就已完成了单元测试及代码覆盖率报告的自动化发邮件了,能及时发现错误,这在很大程度上保证了我们的代码是经测试的,是有效可靠的。下一篇,将讲如何使用findbugs插件进行查虫,包括gradle的配置和jenkins的配置,发送findbugs报告到邮箱,更进一步的提高代码质量。
Jenkins构建Android项目持续集成之单元测试及代码覆盖率的更多相关文章
- Jenkins构建Android项目持续集成之findbugs的使用
Findbugs简介 关于findbugs的介绍,可以自行百度下,这里贴下百度百科的介绍.findbugs是一个静态分析工具,它检查类或者 JAR 文件,将字节码与一组缺陷模式进行对比以发现可能的问题 ...
- 使用jenkins进行Android的持续集成
关于持续集成的定义和意义可以参考它的 百度百科 主要意义有以下几点: 减少风险 减少重复过程 任何时间.任何地点生成可部署的软件 增强项目的可见性 建立团队对开发产品的信心 持续集成的实施 持续集成的 ...
- jenkins部署github项目持续集成
一.先介绍正向代理和反向代理 正向代理 反向代理 二.安装反响代理得到固定域名 http://www.xiaomiqiu.cn/ 三.Jenkins与Github集成 配置前要求: 1.Jenkins ...
- Jenkins + testNg + maven 项目持续集成
搞了一整天,梳理下关键点: 1.项目的pom.xml要配置插件,同时指定testng.xml文件的位置.就被这个卡了好久 <properties> <maven-surefire-p ...
- Net 项目构建基于Jenkins + Github + Mono 的持续集成环境
Net 项目构建基于Jenkins + Github + Mono 的持续集成环境 阅读目录 1 安装 2 配置 3 测试 在Redhat enterprise 6.5 的服务器上,为在gutub 上 ...
- Jenkins +Maven+Tomcat+SVN +Apache项目持续集成构建
详解Jenkins +Maven+Tomcat+SVN +Apache项目持续集成 一:前言 1. Jenkins jenkins版本大全http://mirrors.jenkins-ci.org/ ...
- Framework项目持续集成(jenkins)及集合SonarQube
目录 Framework项目持续集成及集合SonarQube - 前言 CI/CD是什么 -- jenkins 什么是sonarqube?什么是CodeReview? 什么是sonarqube? 什么 ...
- Selenium Web 自动化 - 项目持续集成(进阶)
Selenium Web 自动化 - 项目持续集成(进阶) 2017-03-09 目录 1 背景及目标2 环境配置 2.1 SVN的安装及使用 2.2 新建Jenkins任务3 过程分析 1 背景 ...
- Selenium Web 自动化 - 项目持续集成
Selenium Web 自动化 - 项目持续集成 2017-02-13 目录 1环境准备 1.1 安装git 1.2 安装jenkins 1.3 安装jenkins插件 1.4 jekins ...
随机推荐
- (原创)foef注意事项
原创内容,转载请标明原文地址 我们先来看下下面的代码 //获取文件大小 DWORD Get_File_Size(const char* m_FilePath) { unsigned long size ...
- tab切换插件开发
我开发的tab切换插件,基于jquery库,实现tab标签页的切换.插件的名称为jquery.tabSwitch.js. 插件实现代码如下: ; (function ($) { $.fn.tabSwi ...
- 机器学习:Python实现聚类算法(一)之AP算法
1.算法简介 AP(Affinity Propagation)通常被翻译为近邻传播算法或者亲和力传播算法,是在2007年的Science杂志上提出的一种新的聚类算法.AP算法的基本思想是将全部数据点都 ...
- Docker 镜像小结 - 每天5分钟玩转 Docker 容器技术(21)
本节我们对 Docker 镜像做个小结. 这一部分我们首先讨论了镜像的分层结构,然后学习了如何构建镜像,最后实践使用 Docker Hub 和本地 registry. 下面是镜像的常用操作子命令: i ...
- js背景自适应,学到了
最近在做一个项目,要求实现背景自适应,何为背景自适应呢? 1.如果背景图高度不够,背景height是100%,background-size就应该是 100% auto 2.如果背景图宽度不够,背景w ...
- 如何动态加载js文件,$.getScript()方法的使用
有时候我们需要动态在页面中加载js文件,jquery封装了getScript()方法,不用自己再创建标签了. 写法: $.getScript("name.js",function( ...
- Activiti工作流几种驳回方式的实现与比较
最近公司做的一个项目要实现工作流程的收回,驳回等操作,而采用的工作流引擎并不支持驳回功能,这个项目恰好就我和一个实习生一块做,所以这个问题就落到我的头上来解决了... 客户提出的要求是驳回时要记录日志 ...
- mysql revise
DATABASE create database db_name; use db_name; alter database db_name; drop database db_name; show d ...
- CSS浮动、绝对、相对定位
浮动 float:属性{ float:none; 默认值,对象,不漂浮 float:left; 文本流向对象的右边 float:right; }; 清除浮动 clear:属性{ clear:no ...
- Linux常见命令(二)
随着Linux应用的扩展许多同学开始接触Linux,根据学习Windwos的经验往往有一些茫然的感觉:不知从何处开始学起.虽然Linux桌面应用发展很快,但是命令在Linux中依然有很强的生命力.Li ...