`
lovelease
  • 浏览: 386465 次
社区版块
存档分类
最新评论

Android项目集成Jenkins(JUnit test & Coverage)

阅读更多
为了实现持续集成,提高代码质量,项目要求集成Jenkins,第一次集成Jenkins,花了不少时间,终于还是完成了,这里记录一下整个过程,Jenkins支持很多功能,Android Lint、Check Style、PMD、FindBugs、JUnit Test Report、Coverage Report等等,做下来感觉Coverage这部分的集成相对困难,所以本文主要以”如何在Jenkins中集成Junit & Coverage Report“为主题(至于怎么写JUnit test,不是本文的主题,我们假设项目已经支持JUnit环境了)。

关于Jenkins的集成,网上的文章不算多,这里有一个系列博客比较有参考价值:
http://blog.csdn.net/it_talk/article/details/50267573
有兴趣的可以深入研究一下。我这里会简略提一些必要的集成步骤,还会补充一些集成过程中遇到问题的解决。

1.编写coverage.gradle:
我先把最终的完成脚本贴出来,然后再分别说明。
//代码覆盖率插件
apply plugin: 'jacoco'

android {
// 目前已经不支持通过jacoco{}指定版本了,如果加入这块代码,运行不会出错,但是会有
// warning提示
//    jacoco{
//        version "0.7.6.201602180812"
//    }

    // 项目较小的情况下不需要dexOptions的配置,只有项目方法数超过64K的限制时或者
    // 项目本身接近64K上限但还未超过,加了Junit代码后就超过时(我们项目就属于这种
    // 情况),需要对项目做multidex支持,实现方法很简单,请自行调查。
    // Enable multidex后可能会遇到java.lang.OutOfMemoryError: GC overhead limit exceeded问题,需要此项配置来解决
    dexOptions {
        javaMaxHeapSize "4g"
    }

    buildTypes {
        debug{
            testCoverageEnabled true
        }
    }
}

//jacocoTestReport依赖于connectedAndroidTest task,所以在执行jacoco之前需要先执行connectedAndroidTest,也就是说需要连接测试机(模拟器or真机)
task jacocoAndroidTestReport(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']
    additionalSourceDirs = files(coverageSourceDirs)
    sourceDirectories = files(coverageSourceDirs)
    additionalClassDirs = files(coverageSourceDirs)
    executionData = files("$buildDir/outputs/androidTest-code-coverage/connected/coverage.ec")
}

//jacocoTestReport依赖于test task,所以在执行jacoco之前需要先执行test
task jacocoTestReport(type:JacocoReport,dependsOn:"test"){
    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']
    additionalSourceDirs = files(coverageSourceDirs)
    sourceDirectories = files(coverageSourceDirs)
    additionalClassDirs = files(coverageSourceDirs)
    executionData = files("$buildDir/outputs/test-code-coverage/coverage.ec")
}


其中有两个task:jacocoAndroidTestReport、jacocoTestReport。从他们各自的依赖关系
task jacocoAndroidTestReport(type:JacocoReport,dependsOn:"connectedAndroidTest")

task jacocoTestReport(type:JacocoReport,dependsOn:"test")

我们可以知道jacocoAndroidTestReport其实是针对androidTest测试的,而jacocoTestReport是针对test测试的。androidTest和test是什么?简单的说androidTest就是跑在Android模拟器(AVD)或者真机上的测试代码(包括Android UI测试),test就是跑在jvm上的测试代码,其实就是纯java的iunit test(和server端的junit没啥分别),他们还有各自对应的compile——”androidTestCompile"和"testCompile",关于这部分知识,不清楚的同学可以自行google,总之根据项目需要选择task。

2.将coverage.gradle导入项目的build.gradle中:
apply plugin: 'com.android.library'
// 这里是相对路径,假设coverage.gradle和build.gradle在同一个目录下
apply from: './coverage.gradle'

这样本地的脚本就算完成了,接下来需要配置Jenkins。Jenkins集成coverage其实会依赖JAVA、Android、Gradle环境,如果Jenkins搭在本地,可能就不需要这些步骤(毕竟做开发的不可能没有这些环境),但如果是搭在一台新的远程服务器上,那你可能需要事先搭建以上3个环境,配好环境变量,我没有实际验证过这3个环境是不是必须的,只是我们的远程服务器上Jenkins运行gradle脚本时一开始提示“can't find project ‘gradle’”,于是我单独配置了这些环境,之后还需要保证Jenkins服务器的网络Fan Qiang,否则很可能gradle脚本运行过程中下载一些必要的依赖会失败。

首先在Jenkins上新建一个“构建”,指定要运行的gradle task:

起初我是选择的“Invoke Gradle”,这个需要在服务器上配置gradle环境,但我配好运行还是有问题,所以我换了“Use Gradle Wrapper”,Jenkins会使用我们的gradle wrapper去自动下载gradle,这里就需要保证网络畅通了。“Root Build Script”就是指定你的build.gradle路径,如果不确定${workspace}指向的路径到底是哪里,可以直接运行一下,根据Jenkins日志提示的错误判断出来,总之你要指定正确的build.gradle路径,使Jenkins能找到它,之所以添加一个clean的task,是因为junit运行一次后下次运行如果不删除之前的结果会报错,所以运行之前先clean一次。

然后添加一个”构建后操作“,选择“Publish Junit test result report”:

xml的路径设定为JUnit执行后的XML报告的路径。

之后再添加一个”构建后操作“,选择“Record JaCoCo coverage report”:

“Path to class directories”配置的是编译后.class文件的路径地址,Android都是放在build路径下build\intermediates\classes;“Path to source directories”配置的是java代码路径。

这样一来,Jenkins就会在构建过程中执行我们的task,生成junit结果报告和coverage报告,构建后就会自动收集结果病生成报告。

接下来我们分析一下coverage.gradle,以及上述集成过程中可能会遇到的问题

一般来说,通过以下4步即可完成覆盖率的集成:
(1)引入jacoco插件;
//代码覆盖率插件
apply plugin: 'jacoco'

(2)打开coverage:
android {
    buildTypes {
        debug{
            testCoverageEnabled true
        }
    }
}

(3)创建task:
即jacocoAndroidTestReport 和 jacocoTestReport。
(4)将coverage.gradle导入项目的build.gradle中:
apply plugin: 'com.android.library'
// 这里是相对路径,假设coverage.gradle和build.gradle在同一个目录下
apply from: './coverage.gradle'

如此,你的项目应该已经集成了coverage功能,但是如果你的项目很大,不得不分包(只有androidTest下面的测试可能会遇到该问题)时,就需要对项目做multidex的支持,之后你会发现64K的问题没有了,但是你可能又遇到新的问题:
Error:UNEXPECTED TOP-LEVEL ERROR:
java.lang.OutOfMemoryError: GC overhead limit exceeded

此时,下面的设置就派上用场了:
dexOptions {
        javaMaxHeapSize "4g"
    }

好了,GC的问题也解决了,终于能跑通了,但是控制台还是会出现一些warnings,虽然不影响构建过程,但强迫症的同学都不愿意看到它们,其实解决方法很简单。

warning_1:
To honour the JVM settings for this build a new JVM will be forked. Please consider using the daemon

解决方法:在gradle.propertie文件中增加以下配置
org.gradle.daemon=true


warning2:
Running dex as a separate process.
To run dex in process, the Gradle daemon needs a larger heap.
It currently has 1996 MB.
For faster builds, increase the maximum heap size for the Gradle daemon to at least 4608 MB (based on the dexOptions.javaMaxHeapSize = 4g).
To do this set org.gradle.jvmargs=-Xmx4608M in the project gradle.properties.
For more information see https://docs.gradle.org/current/userguide/build_environment.html

关于这个warning的原因,可以看这里http://stackoverflow.com/questions/37090135/to-run-dex-in-process-the-gradle-daemon-needs-a-larger-heap-it-currently-has-a,其实就是你指定了 javaMaxHeapSize "4g" 后引起的(android studio默认的是1g)
解决方法:在gradle.propertie文件中增加以下配置
# Default value: -Xmx1024m -XX:MaxPermSize=256m
org.gradle.jvmargs=-Xmx4608m -XX:MaxPermSize=1024m

以上就是整个过程了,如果大家在集成中遇到其他问题,就请自行解决吧。
  • 大小: 83.1 KB
  • 大小: 59.7 KB
  • 大小: 52.1 KB
分享到:
评论

相关推荐

    androidStudio测试代码

    Android Studio提供了测试覆盖率报告,可以在"Build > Analyze Test Coverage"中查看。这有助于评估哪些代码已通过测试,哪些尚未覆盖。 七、持续集成与测试 将测试集成到持续集成(CI)系统,如Jenkins、Travis C...

    Testing.with.Junit【高清PDF版】

    - Continuous Integration工具:如Jenkins、Travis CI,可以集成Junit自动执行测试,确保代码提交时的稳定性。 6. 使用Junit的最佳实践: - 单元测试应该是独立的,不应依赖外部资源或状态。 - 每个测试方法应只...

    Android test测试小demo

    "Android test测试小demo"是一个典型的测试项目,用于开发者学习和实践如何进行Android应用的测试。在这个项目中,你可能会遇到以下几个重要的Android测试知识点: 1. **JUnit与Espresso**: JUnit是Java领域广泛...

    Android 单元测试资料

    1. **配置项目**:添加JUnit和AndroidX.Test库到项目的build.gradle文件,以及启用testOptions以获取详细的测试报告。 2. **编写测试**:使用JUnit4的断言方法(如assertEquals、assertTrue等)来验证方法的输出是否...

    Android代码-安卓测试学习

    9. **Android Test Orchestrator**:在大型项目中,测试可能会因为依赖和并发问题导致失败。Android Test Orchestrator解决了这个问题,它按顺序运行每个测试,确保每个测试的环境独立,提高了测试的稳定性。 10. *...

    android_test:对自己的考验

    通过这个"android_test-master"项目,开发者可以深入学习如何构建和执行各种类型的Android测试,包括单元测试、UI测试和集成测试,以及如何优化测试流程,提高测试效率和代码质量。在实践中,理解并熟练运用这些知识...

    Android工程使用Jacoco输出测试覆盖率报告

    JaCoCo是一款强大的Java代码覆盖率工具,它能够与JUnit、TestNG等测试框架无缝集成,为开发者提供详细的单元测试覆盖率数据。在Android项目中,JaCoCo可以帮助我们了解测试用例覆盖了多少代码,哪些部分可能仍未被...

    cobertura1.9.1

    4. **运行Ant脚本**:执行Ant构建命令,例如`ant test`或`ant coverage`,这将运行JUnit测试,并通过Cobertura收集覆盖率数据。 5. **查看报告**:Cobertura会生成HTML格式的覆盖率报告,开发者可以浏览这些报告...

    UnitTestWithJenkins

    单元测试与Jenkins结合是软件开发中的重要实践,它能够帮助开发者确保代码的质量,并在持续集成环境中自动执行测试。在Python编程中,我们通常使用unittest模块进行单元测试,而Jenkins作为一个流行的持续集成工具,...

    YES-Android-Automation

    - **Android Studio 的集成测试工具**:Android Studio 提供了丰富的测试工具,如Test Coverage报告,用于查看测试覆盖率,还有Android Profiler,用于性能分析。 - **持续集成/持续部署(CI/CD)**:如Jenkins、...

    testlab_application

    6. **持续集成/持续部署(CI/CD)**:项目可能使用Jenkins、Travis CI、CircleCI等工具进行自动化构建和测试,确保每次代码提交后都能快速得到反馈。 7. **Spring Boot Test**:如果项目基于Spring Boot,那么它可能...

    Jenkiins_test

    测试集成:在构建步骤中,添加测试命令,例如`python setup.py test`或`pytest --junitxml=test_results.xml`,这将运行项目中的测试并生成测试报告。\n\n4. 代码覆盖率:如果需要计算测试覆盖率,可以使用coverage...

    codelab-android-testing:代码实验室开发

    - **Test Coverage**:通过设置Android Studio中的代码覆盖工具,可以查看测试覆盖了多少代码,以评估测试的完整性。 2. ** Espresso UI 测试**: - **Espresso** 是Android平台上的UI测试框架,用于编写直观、...

    Manning.Test.Driven.TDD.and.Acceptance.TDD.for.Java.Developers

    掌握JUnit的基本用法,如@Test注解、断言、@Before和@After方法等,是进行TDD的基础。 2. Mockito:这是一个流行的Java模拟框架,允许在测试中模拟对象的行为,以便隔离被测试代码,避免外部依赖对测试的影响。 3....

    AndroidCodes:Android原始测试实例-android

    8. 自动化测试(Automated Testing):持续集成/持续部署(CI/CD)工具,如Jenkins、Travis CI或CircleCI,能够自动化执行测试,确保每次代码提交后都能快速得到反馈。 在这个开源项目"AndroidCodes-master"中,可能...

    pls-wodm_autotest.rar

    5. Continuous Integration (CI)工具:为了确保每次代码更改后都能快速发现潜在问题,项目可能集成了Jenkins、Travis CI或者GitLab CI/CD等CI工具。这些工具可以自动化地运行测试套件,提供持续的反馈。 6. Code ...

    common-test-utils

    10. **持续集成(CI/CD)**:对于大型项目,持续集成和持续部署是必不可少的。库可能提供了与Jenkins、Travis CI或GitLab CI等工具的集成,以自动化测试和部署流程。 以上是对"common-test-utils"的初步解析,具体...

    TestingInAndroid

    对于Android项目,常用的CI/CD工具有Jenkins、Travis CI、CircleCI和GitHub Actions,它们可以帮助团队实现自动化测试和发布流程。 总结来说,"TestingInAndroid"涵盖了一系列测试技术和工具,从单元测试到UI测试,...

    jekins_unitest

    要在Jenkins中运行unittest测试,首先需要安装Jenkins插件,如`Publish JUnit test result report`,该插件可以解析unittest生成的XML测试报告。然后,在Jenkins的工作流中添加构建步骤,运行Python脚本执行单元测试...

    java_test

    6. **持续集成(CI)**: 为了确保代码库的质量,"java_test"可能与持续集成工具如Jenkins、Travis CI或GitHub Actions集成。每次代码提交时,这些工具会自动构建项目并运行测试,从而快速发现引入的错误。 7. **代码...

Global site tag (gtag.js) - Google Analytics