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 ...
随机推荐
- linux centos7.0安装subversion
安装环境以及软件版本如下: subversion使用1.8.17版本,CentOS7.0(64位) 安装svn共需要使用如下软件,apr-1.5.2.tar.gz.apr-util-1.5.4.tar ...
- 5.Lock接口及其实现ReentrantLock
jdk1.7.0_79 在java.util.concurrent.locks这个包中定义了和synchronized不一样的锁,重入锁——ReentrantLock,读写锁——ReadWriteLo ...
- Spring MVC动态切换数据源(多数据库类型)
最近由于项目需求,需要将Sql Server 和 Mysql 两种数据库整合到一个项目,项目的用到的框架是SSM. 因此尝试了利用AOP切面来切每次执行的Servcie方法,根据Service所在的包 ...
- stm之SPI通信协议
SPI (Serial Peripheral interface),顾名思义就是串行外围设备接口.SPI是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线,节约了芯片的管脚,同时为P ...
- 【java8】慎用java8的foreach循环
虽然java8出来很久了,但是之前用的一直也不多,最近正好学习了java8,推荐一本书还是不错的<写给大忙人看的javase8>.因为学习了Java8,所以只要能用到的地方都会去用,尤其是 ...
- Catalog Service - 解析微软微服务架构eShopOnContainers(三)
上一篇我们说了Identity Service,因为其基于IdentityServer4开发的,所以知识点不是很多,今天我们来看下Catalog Service,今后的讲解都会把不同的.重点的拿出来讲 ...
- 【转】Delphi多线程编程
文章来源: http://liukun966123.my.gsdn.net/2004/10/22/4797/ Delphi中有一个线程类TThread是用来实现多线程编程的,这个绝大多数Delphi书 ...
- laytpl : 一款非常轻量的JavaScript模板引擎
//假设你得到了这么一段数据 var data = { title: '前端圈', intro: '一群码js的骚年,幻想改变世界,却被世界改变.', list: [{name: '贤心', city ...
- 《Python编程从入门到实践》第三章_列表简介
什么是列表呢? 官方说明就是由一些列按特点顺序排列的元素组成.其实可以看出很多个字符串的有序组合吧,里面的内容可以随时的删除,增加,修改. 下面这个就是一个列表,python打印列表的时候会将中括号和 ...
- js获取页面宽高
网页可见区域宽:document.body.clientWidth网页可见区域高:document.body.clientHeight网页可见区域宽:document.body.offsetWidth ...