编写移动应用程序很难,编写好的和可维护的应用程序更加困难了。在开发过程中,我们需要保证对代码库的每次修改不会降低代码质量和功能的可用性。
  在现代的移动应用开发中,很难想象在没有编写测试特别是单元测试的情况下,你可以做出一个可靠的和可维护的应用。但我们经常遇到一个问题:要编写多少的测试用例才能足够保证这段代码能够被测试正确的覆盖。嗯,这没有明确的答案,但我想介绍一个名为 JaCoCo 这款很棒的工具,它有助于保证有价值的代码被单元测试覆盖到。
  JaCoCo 全称是 Java Code Coverage tool,它已经在 Java 开发者中使用数十年了,但如果配置得当的话, Android 开发者也可以利用它获得益处。社区已经有很多文章介绍 Android 工程中如何配置 JaCoCo 从而生成测试覆盖报告,因此我不再深入介绍这个主题。相反我将展示如何为 JaCoCo 测试覆盖配置自动校验功能,从而方便将其引入你的构建或者 CI 管道(pipeline)中。
  首先让我们看一个很简单的 App,它包含两个页面:登录页面和主页面。
  请注意,这个示例工程只作演示用途,并不具备作为生产版本发布和使用的能力。

  你可以在 Github:https://github.com/sgrekov/AndroidJacocoSample 上找到这个工程的完整代码。
  在这个示例工程中我实现了一个很基础的 MVP 模式。这意味着我们将 Activities 视为被动的 View,所有有用的 UI 逻辑放在 Presenters 中。让我们仔细看下 LoginPresenter,它有一个键盘输入处理,登录和密码的校验,以及授权逻辑本身。如果一切校验没有问题的话,那么登录成功后我们进入 MainActivity。在 LoginPresenterTest 中有一些单元测试。MVP 模式的规则是保持 View 层拥有尽可能少的代码,同时,将业务逻辑保留在 Presenters 中,从而使得这部分逻辑代码能够很容易被单元测试覆盖到。我们将按这种方式来配置 JaCoCo。我们将忽略 View 层和一些 Android 相关的类,为除此以外其他的类的代码生成测试覆盖报告。

  如果我们的工程结构是按照特性来组织的,那么通过配置 'com/androidjacoco/sample/**/view/**.*' 这个过滤器规则可以忽略现在以及将来可能增加的所有的 View 类。
  现在,如果我们在命令行中执行:

  我们将得到类似下面这样一份报告:

  这里我们可以看到报告中展示了一些数据类和 Presenters 的覆盖率。
  我们对下面三列感兴趣:
  Missed Instructions:提供关于被执行(译者注:指被单元测试覆盖到)或者没有被执行的代码量信息,单位是一条 Java 字节码指令。
  Missed Branches:用于计算一个方法中此类分支的总个数,并确定被执行或者没有被执行的分支数量。
  Classes:一个类只有当其中至少一个方法被执行过,才认为这个类是已执行的。
  关于报告的更详细信息可以参见:http://www.jacoco.org/jacoco/trunk/doc/counters.html。
  让我们看一下 LoginPresenter 类,并确保其中确实有很多没有被执行到的指令和分支。

  这里也要注意一下,匿名类,例如上面代码中的 SingleObserver 或者 Consumer 类,在报告中会当作独立的类来计算,正如我们在上面报告的 com.androidjacoco.sample.login.presenter 这个包所对应的 classes 列的值可以看到的。