注册 登录
  • 欢迎访问Sharezer Blog

Gradle for Android 第六篇 (测试)

Gradle sharezer 117次浏览 未收录 0个评论

原文地址 https://segmentfault.com/a/1190000004260141

这会是一个系列,所以如果你看完这篇文章,请看下列文章:

Gradle for Android 第一篇 (从 Gradle 和 AS 开始)
Gradle for Android 第二篇 (Build.gradle 入门)
Gradle for Android 第三篇 (依赖管理)
Gradle for Android 第四篇 (构建变体)
Gradle for Android 第五篇 (多模块构建)
Gradle for Android 第六篇 (测试)
Gradle for Android 第七篇 (Groovy 入门)

由于现阶段 Android 开发趋于敏捷开发,再加上国内大大小小的互联网公司都在做 app,导致很多开发人员对单元测试没有基本的概念,但是本篇博文不会为大家讲解什么是单元测试,功能测试,而是讲解如何在 Android studio 上利用 gradle 使用现阶段流行的测试框架等。

为了确保 app 或者 library 库的质量,有一个完整的测试非常重要。很长一段时间,Android 开发工具都缺乏针对完整性测试的支持,但是最近,google 为之做了大量的工作,其让开发者做测试变得更加容易了,一些旧的框架更新了版本,新的框架也被加入进来。我们现在不仅可以在 Android studio 中运行这些测试,甚至可以用 gradle 通过命令行直接执行。

所以基于此,我们这一章,将会为大家介绍几种测试 Android app 的方式,我们也会深究之为何 gradle 可以帮助测试自动化。

这一章节我将遵循以下内容:

  • 单元测试

  • 功能测试

  • 测试覆盖率

单元测试

相信大家都有了单元测试的概念,那么好的单元测试不仅仅能够确保 app 的质量,同时还可以让新代码开发更加容易。Android studio 和 gradle android 插件默认支持单元测试,但是在你使用它之前,你仍需配置一下。

JUnit

JUnit 测试界非常流行, 其使得测试代码容易编写和维护, 但是记住,JUnit 只能测试逻辑代码,针对和 Android SDK 相关的代码其会报相应的错误。

在你开始编写 junit 测试之前,你需要为其新建一个目录。通常呢,这个会被叫做 test,其会和你的 main 文件夹平级。

app
└─── src
     ├─── main
          ├─── java
          │    └─── com.example.app
          └─── res
     └─── test
          └─── java
               └─── com.example.app

你可以在 test 目录下创建测试类。

我建议你使用 JUnit 4, 你可以将其作为依赖添加到你的依赖库。

dependencies {
       testCompile 'junit:junit:4.12'
}

注意到你使用了 testCompile,这意味着该 jar 包只会在你测试的时候导入 apk。

如果你有其他的构建版本呢,而你又只是想为特定版本添加该 jar,你只需要这么做:

dependencies {
       testPaidCompile 'junit:junit:4.12'
 }

当所有的事情都 OK 了,就是时候开始写测试代码了。下面是简单的测试代码:

import org.junit.Test;
   import static org.junit.Assert.assertEquals;
   public class LogicTest {
       @Test
       public void addingNegativeNumberShouldSubtract() {
           Logic logic = new Logic();
           assertEquals("6 + -2 must be 4", 4, logic.add(6, -2));
           assertEquals("2 + -5 must be -3", -3, logic.add(2, -5));
       }
}

那么如何跑起来呢,也很简单,运行 gradlew test。如果你只是想再特定版本中跑呢,那就加一个呗 gradlew testDebug。如果测试失败,gradle 将会打印相关错误,如果所有测试成功通过,那么会显示 BUILD SUCCESSFUL 。

可能你会说,单个测试用例导致整个测试失败,这样不好,如果你想把整个测试案例都跑一遍,那也很简单啊:

$ gradlew test --continue

执行测试任务不仅仅是跑完所有的测试,而且其还会为你创建一份测试报告,你可以找到它 app/build/reports/tests/debug/index.html。这份报告让你能够更快的发现问题,我觉得最重要的是当你将你的测试自动化后,这会非常有用,gradle 会为每个构建版本都创建一份测试报告。如果你执行测试成功,你的测试报告会是这个样子:

Gradle for Android 第六篇 (测试)

说了这么多原始的做法,那么看看 Android studio 怎么运行测试的吧。右键项目或者选择开始按钮。。这个太基础不多说了,运行成功是这个样子:

Gradle for Android 第六篇 (测试)

好了,junit 测试讲完了,是不是很简单。

如果你想测试你的关联 Android sdk 代码怎么办,单元测试不是一个好主意,幸运的是,有多个依赖包供你选择,其中最出名的是 Robolectric,其可以让你更方便的测试 Android 功能,并且还不用在设备或者模拟器上运行。

Robolectric

通过使用 Robolectrie,你可以编写测试类,这些类可以使用 Android SDK 和资源文件,当然其还是跑在 jvm 上,这会让你测试 app 更加迅速。

在开始使用 Robolectrie 之前,你需要添加依赖。注意除了 Robolectric 依赖,你需要添加 JUnit 包。

apply plugin: 'org.robolectric'
   dependencies {
       compile fileTree(dir: 'libs', include: ['*.jar'])
       compile 'com.android.support:appcompat-v7:22.2.0'
       testCompile 'junit:junit:4.12'
       testCompile'org.robolectric:robolectric:3.0'
       testCompile'org.robolectric:shadows-support:3.0'
}

Robolectrie 测试类也需要写在 test 文件夹下,举个例子:

@RunWith(RobolectricTestRunner.class)
   @Config(manifest = "app/src/main/AndroidManifest.xml", sdk = 18)
   public class MainActivityTest {
       @Test
       public void clickingButtonShouldChangeText() {
           AppCompatActivity activity = Robolectric.buildActivity
             (MainActivity.class).create().get();
           Button button = (Button)
             activity.findViewById(R.id.button);
           TextView textView = (TextView)
             activity.findViewById(R.id.label);
           button.performClick();
           assertThat(textView.getText().toString(), equalTo
             (activity.getString(R.string.hello_robolectric)));
        } 
    }

功能测试

神马是功能测试,其是用来测试一个 app 的多个模块是否能够正常工作。举个栗子,你可以创建一个功能测试来确保你点击某一按钮后是否会有一个新的 activity。依然,我们会有很多框架。但是在这里,我推荐 Espresso。

Espresso

google 创建 Espresso 的目的就是在于简化开发人员编写功能测试用例。这个包是由 Android support repository 提供,所以你可以通过 SDK Manager 使用它。

在运行测试用例之前,你需要定义一个 runner。google 提供了 AndroidJUnitRunner 测试 runner, 这将帮助你在手机上运行 Unit 测试。测试 runner 可以帮你安装 apk 以及一个测试 apk,执行所有测试,生成测试报告。

假设你下载了 support library 包,那么你需要这么定义:

defaultConfig {
       testInstrumentationRunner
         "android.support.test.runner.AndroidJUnitRunner"
   }

当然你需要添加一些依赖包:

dependencies {
       compile fileTree(dir: 'libs', include: ['*.jar'])
       compile 'com.android.support:appcompat-v7:22.2.0'
       androidTestCompile 'com.android.support.test:runner:0.3'
       androidTestCompile 'com.android.support.test:rules:0.3'
       androidTestCompile
         'com.android.support.test.espresso:espresso-core:2.2'
       androidTestCompile
         'com.android.support.test.espresso:espresso-contrib:2.2'
   }

注意到这些依赖包使用了 androidTestCompile,其不同于 testCompile。当你直接运行时,会报错:

Error: duplicate files during packaging of APK app-androidTest.apk
     Path in archive: LICENSE.txt
     Origin 1: ...\hamcrest-library-1.1.jar
     Origin 2: ...\junit-dep-4.10.jar

其意思也很清楚,因为多个文件导致,你可以简单处理下:

android {
     packagingOptions {
     exclude 'LICENSE.txt'
  }
}

注意:功能测试需要放在 AndroidTest 目录下,下面是测试用例:

@RunWith(AndroidJUnit4.class)
   @SmallTest
   public class TestingEspressoMainActivityTest {
       @Rule
       public ActivityTestRule<MainActivity> mActivityRule = new
         ActivityTestRule<>(MainActivity.class);
       @Test
       public void testHelloWorldIsShown() {
           onView(withText("Hello world!")).check
             (matches(isDisplayed()));
        } 
    }

功能测试也有测试报告,当正确执行后,应该是这样的:

Gradle for Android 第六篇 (测试)

最后可能有朋友问,在 Android studio 中执行测试,那就附图吧:

Gradle for Android 第六篇 (测试)

Gradle for Android 第六篇 (测试)

测试覆盖率

一旦你在你的项目中使用到了测试,那么你肯定想知道你的测试覆盖量。很真实,依然有很多测试覆盖率工具,我推荐的是 Jacoco。

Jacoco

有一份覆盖率报告,很简单。你只需要配置一下:

buildTypes {
     debug {
       testCoverageEnabled = true
     }
}

当你执行完构建,你可以在 app/build/ outputs/reports/coverage/debug/index.html 中找到,每个版本都会有一个报告。测试覆盖率会是这样的:

Gradle for Android 第六篇 (测试)

你甚至可以通过点击查看更多信息,可以看到哪一行代码被测试。

总结

在这一章,我们学习了如何测试,我们学习了简单的单元测试,以及 Robolectric 测试。我们学习了功能测试,以及学习了如何使用 Espresso。最好,我们学会了如何查看测试覆盖率报告。

在下一章,我将会带来最重要的一章,即自定义化构建过程,创建自定义 tasks 和插件。当然了我们会首先介绍 Groovy 语法,理解其语法让你能够更轻松的理解 gradle 是如何工作的。


Sharezer , 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权 , 转载请注明Gradle for Android 第六篇 (测试)
喜欢 (0)
[liangshaoze@sina.cn]
分享 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址