Android项目持续集成之单元测试及代码覆盖率

转载 2016年08月30日 14:44:53

转载自: http://blog.csdn.net/it_talk/article/details/50267573

单元测试

  在软件开发中一直在推崇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

Gradle配置jacoco

  Jacoco是一个开源的覆盖率工具。这里讲下gradle如何配置。 
  首先要在项目的build.gradle引入插件,语句如下:

 apply plugin: 'jacoco'
  • 1

  然后注明使用的版本号

jacoco{
        version "0.7.4.201502262128"
    }
  • 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

  最后,打开testCoverageEnabled,需要注意的是,打开该属性的话,在断点调试的时候会导致方法参数值丢失(看不到),所以在调试的时候要记得把它关掉。

buildTypes {
        debug{
            testCoverageEnabled true
        }
    }
  • 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

生成报告

配置完上面的步骤之后,打开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之后就会自动生成报告。

Android Lint报告

上图中不用填写入任何路径,默认的即可。

邮件配置及gradle执行命令的修改

首先,我们先修改下邮件的发送内容。

邮件内容修改

我们在上一节的基础上,只是新增加了以上3中报告的地址。 
接着,还需要修改gradle 执行的命令。

构建命令修改

项目的build.gradle修改下

build.gradle

去掉connectedAndroidTest的关联,因为我们已经独立使用命令执行connectedAndroidTest了,所以jenkins服务器在跑job的时候,请确保已经打开了Android模拟器,否则会出错。

查看邮件报告

配置完以上的步骤之后,将代码push到github上,等待jenkins触发构建或者我们手动执行构建都可以。 
邮件内容 
邮件里增加了配置里相应修改的内容。

注意:因为我的项目是一个lib项目,而在Android里lib项目生成的jar包是一个aar,所以这里的单元测试,我是写在lib项目里,然后构建产物,我也修改为获取aar包,修改如下: 
构建产物修改 
邮件附件

总结

跟着上面的步骤来,我们就已完成了单元测试及代码覆盖率报告的自动化发邮件了,能及时发现错误,这在很大程度上保证了我们的代码是经测试的,是有效可靠的。下一篇,将讲如何使用findbugs插件进行查虫,包括gradle的配置和jenkins的配置,发送findbugs报告到邮箱,更进一步的提高代码质量。

看下其他文章: 
1、Jenkins构建Android项目持续集成之简介篇 
2、Jenkins构建Android项目持续集成之Jenkins的安装篇 
3、Jenkins构建Android项目持续集成之系统配置篇
4、Jenkins构建Android项目持续集成之创建项目 
5、Jenkins构建Android项目持续集成之单元测试及代码覆盖率 
6、Jenkins构建Android项目持续集成之findbugs的使用

相关文章推荐

获取Android代码测试覆盖率详解

Pre 假定APK所在包为net.clasnake.project,工程主目录为/folder。 Step 1 插桩 首先下载EmmaInstrument.rar,解压后包含四个文件...

单元测试代码覆盖率的浅谈

在做单元测试时,代码覆盖率常常被拿来作为衡量测试好坏的指标,甚至,用代码覆盖率来考核测试任务完成情况,比如,代码覆盖率必须达到80%或 90%。于是乎,测试人员费尽心思设计案例覆盖代码。用代码覆盖率来...

OO系统分析员之路--什么是用例

用例是什么?其原始英文是usecase,直译过来就成了用例。这也是一个比较贴切的叫法了,从字面的直接理解就是使用的例子。另一种比较流行的定义是用例就是与使用者(actor)交互的,并且给使用者提供可观...

Android获取CPU信息(CPU名字和主频)

http://blog.csdn.net/hudashi/article/details/8462539 文章参照自:http://www.2cto.com/kf/201206/13...

Jenkins构建Android项目持续集成之单元测试及代码覆盖率

单元测试  在软件开发中一直在推崇TDD(测试驱动开发),但是一直不能被有效的执行或者并不是真正的测试驱动开发(先开发后写单元测试),因为我们懒!而Android开发又是大多应用层面的开发,很多都是和...

结合junit + ant + emma实现Android项目单元测试代码覆盖率统计

结合junit + ant + emma实现Android项目单元测试代码覆盖率统计   1.建立一个简单的android应用 应用的界面如下,首先是两个id分别为value1和value2的输...

VS2015+TFS CI集成中的单元测试与代码覆盖率报告

CI集成建制流程(VS2015+TFS Server) 单元测试 配置对应的测试项目 单元测试用例的命名规则(建议) 测试对象 测试方创建的对象 ...

项目管理大法归档 - 思维导图、原型工具、接口测试、设计模式、版本管理、单元测试、持续集成、代码审查、Bug 跟踪

项目管理大法归档 - 思维导图、原型工具、接口测试、设计模式、版本管理、单元测试、持续集成、代码审查、Bug 跟踪...
  • sleks
  • sleks
  • 2015年08月31日 06:23
  • 1531

统计 Android 单元测试代码覆盖率

为程序编写单元测试对于我一个境界比较low的程序员来说,简直就是噩梦,但是不得承认,为项目写测试是个非常正确、必要的工作,尤其是当项目越来越大,代码越来越多,测试代码可以及时检查出一次改动所带来的影响...

eclemma单元测试代码覆盖率工具

  • 2015年06月18日 09:53
  • 1.23MB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Android项目持续集成之单元测试及代码覆盖率
举报原因:
原因补充:

(最多只允许输入30个字)