【转载】Gradle for Android 第六篇( 测试)
由于现阶段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会为每个构建版本都创建一份测试报告。如果你执行测试成功,你的测试报告会是这个样子:
说了这么多原始的做法,那么看看Android studio怎么运行测试的吧。右键项目或者选择开始按钮。。这个太基础不多说了,运行成功是这个样子:
好了,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()));
}
}
功能测试也有测试报告,当正确执行后,应该是这样的:
最后可能有朋友问,在Android studio中执行测试,那就附图吧:
测试覆盖率
一旦你在你的项目中使用到了测试,那么你肯定想知道你的测试覆盖量。很真实,依然有很多测试覆盖率工具,我推荐的是Jacoco。
Jacoco
有一份覆盖率报告,很简单。你只需要配置一下:
buildTypes {
debug {
testCoverageEnabled = true
}
}
当你执行完构建,你可以在app/build/ outputs/reports/coverage/debug/index.html中找到,每个版本都会有一个报告。测试覆盖率会是这样的:
你甚至可以通过点击查看更多信息,可以看到哪一行代码被测试。
总结
在这一章,我们学习了如何测试,我们学习了简单的单元测试,以及Robolectric测试。我们学习了功能测试,以及学习了如何使用Espresso。最好,我们学会了如何查看测试覆盖率报告。
在下一章,我将会带来最重要的一章,即自定义化构建过程,创建自定义tasks和插件。当然了我们会首先介绍Groovy语法,理解其语法让你能够更轻松的理解gradle是如何工作的。
【转载】Gradle for Android 第六篇( 测试)的更多相关文章
- Gradle for Android 第三篇( 依赖管理 )
依赖管理 这会是一个系列,所以如果你还没有看我之前的几篇文章,请先查看以下文章: Gradle for Android 第一篇( 从 Gradle 和 AS 开始 ) Gradle for Andro ...
- 【转载】Gradle for Android 第四篇( 构建变体 )
当你在开发一个app,通常你会有几个版本.大多数情况是你需要一个开发版本,用来测试app和弄清它的质量,然后还需要一个生产版本.这些版本通常有不同的设置,例如不同的URL地址.更可能的是你可能需要一个 ...
- 【转载】Gradle for Android 第五篇( 多模块构建 )
Android studio不仅允许你为你的app和依赖库创建模块,同时也可为Android wear,Android TV,Google App Engine等创建模块,而这些单独的模块又可以在一个 ...
- 【转载】Gradle for Android 第三篇( 依赖管理 )
依赖管理是Gradle最闪耀的地方,最好的情景是,你仅仅只需添加一行代码在你的build文件,Gradle会自动从远程仓库为你下载相关的jar包,并且保证你能够正确使用它们.Gradle甚至可以为你做 ...
- 深入理解gradle编译-Android基础篇
深入理解gradle编译-Android基础篇 导读 Gradle基于Groovy的特定领域语言(DSL)编写的一种自动化建构工具,Groovy作为一种高级语言由Java代码实现,本文将对Gradle ...
- 【朝花夕拾】Android自定义View篇之(六)Android事件分发机制(中)从源码分析事件分发逻辑及经常遇到的一些“诡异”现象
前言 转载请注明,转自[https://www.cnblogs.com/andy-songwei/p/11039252.html]谢谢! 在上一篇文章[[朝花夕拾]Android自定义View篇之(五 ...
- 【转】gradle for android 第一篇
正如大家所见,这是本英文书,而由于国内的gradle翻译资料不全,所以特次开辟专栏,翻译gradle for android这本书,同时添加自己的心得体会以及在实际工作上的实战,希望大家能够喜欢. 如 ...
- 第六篇 ANDROID窗口系统机制之显示机制
第六篇 ANDROID窗口系统机制之显示机制 ANDROID的显示系统是整个框架中最复杂的系统之一,涉及包括窗口管理服务.VIEW视图系统.SurfaceFlinger本地服务.硬件加速等.窗口管理服 ...
- Gradle 实现 Android 多渠道定制化打包
Gradle 实现 Android 多渠道定制化打包 版权声明:本文为博主原创文章,未经博主允许不得转载. 最近在项目中遇到需要实现 Apk 多渠道.定制化打包, Google .百度查找了一些资料, ...
随机推荐
- HTML基础——表格的应用
一.表格标签 1.基本格式: 每个表格由 table 标签开始. 每个表格行由 tr 标签开始. 每个表格数据由 td 标签开始. 例如: <html> <head> < ...
- 利用Dynamics 365 Customer Engagement的标准导入功能导入附件。
我是微软Dynamics 365 & Power Platform方面的工程师罗勇,也是2015年7月到2018年6月连续三年Dynamics CRM/Business Solutions方面 ...
- JS 输出
JS 输出 JavaScript 通常用于操作 HTML 元素. 操作 HTML 元素 如需从 JavaScript 访问某个 HTML 元素,您可以使用 document.getElementByI ...
- Spring Boot 2 使用自定义配置
在application.yml定义配置后,可以使用Environment来读取配置,也可以使用@Value注解让业务代码去读取配置.如果属性较多,可以定义属性映射对象. 开发环境:IntelliJ ...
- 高性能go服务之高效内存分配
高性能go服务之高效内存分配 手动内存管理真的很坑爹(如C C++),好在我们有强大的自动化系统能够管理内存分配和生命周期,从而解放我们的双手. 但是呢,如果你想通过调整JVM垃圾回收器参数或者是优化 ...
- mssql sqlserver 将逗号分隔的一列数据转换为多列数据的方法分享
转自:http://www.maomao365.com/?p=10278 摘要: 下文讲述sqlserver中将使用逗号组合的单列数据,分隔为多列数据的方法 实验环境:sql server 2012 ...
- Golang防止多个进程重复执行
创建锁文件 lockFile := "./lock.pid" lock, err := os.Create(lockFile) if err != nil { log.Fatal( ...
- Scrum会议(第十一周)
十一周会议 1.任务分配: github相关代码 2.会议记录: 总结并阐述了自己在上周存在的问题以及解决了自己把自己的issue发在了自己的github,并没有把问题发在我们项目小组的项目的issu ...
- JMeter基础知识系列一
1.Jmeter简介: Apache Jmeter可以用于对静态和动态的资源(文件.web动态语言-PHP.java.ASP.net.java对象.数据库和查询.FTP服务器等)的性能进行测试.最初用 ...
- 普通结果集ResultSet和离线结果集RowSet(四)
数据库的查询操作会得到一系列数据,JDBC API也提供了相关对象来接收查询结果集. 一.ResultSet java.sql.ResultSet接口表示数据库查询的结果集. JDBC提供以下连接方法 ...