Android Testing Codelab
Android测试代码实验室
- 学习目的:如何使用Android Testing Support Library即ATSL在开发中进行测试,包括:单元测试,UI测试等
- 学习资源:Google提供的一个完整的程序包和教程
- Google代码实验室主页: https://codelabs.developers.google.com/
- AndroidTesting Codelab主页:Android Testing Codelab
- 学习步骤:下载代码包按照教程结合Androidstudio来进行学习。
学习笔记:
教程目录:
整个教程分为了11个部分:
- 1.介绍了整个project的配置环境和项目预览
- 2.介绍了如何获取zip源码以及zip包的目录结构,和下载到Android手机号如何使用Notes。
- 3.引入了Android上的测试概念,并介绍了一个Google集成的测试包。 Android Testing Support library (ATSL)。
- ATSL:是一个专门用于Android上的集成的测试框架。
- 包含了以下几个不同功能的测试工具包:包含了单元测试Junit 4和UI测试工具:Espresson和 UI Automator.
- It has a JUnit 4-compatible test runner (AndroidJUnitRunner) and functional UI testing through Espresso and UI Automator.
- 4.介绍了 Android的MVP架构
- 5.介绍了MVP的实践,即如何在项目中构造MVP架构的Android项目
- 6.如何使用JUnit4 and Mockito进行单元测试
- 7.如何使用Espresso进行UI测试
- 8.Bonus: Espresso-Intents
- 9.Bonus: Espresso-Contrib
- 10.Bonus: Idling resources
- 11.Bonus: Code Coverage//代码覆盖
知识点笔记
上述目录的第1节到第3节都是简单的概念没有特别需要注意的地方,从第四节开始记录:
第4节介绍了MVP的设计模式:
在Android开发中,我们可以使用不同的层次结构来进行开发,但是一种好的设计模式可以使得我们的APP代码更容易测试和被人理解。MVP就是一种好的设计模式,使用MVP模式能将我们APP的数据和视图以及逻辑进行很好的分离,提高了代码内聚降低了耦合。
**MVP全名:Model-View-Presenter,如下图 **
- In our app, we follow the MVP pattern, separating the internal data model, from a passive view through a presenter that handles the logic of our application.
- 将内部的数据模型与UI的View进行完全的分离,使用presenter来处理业务逻辑连接View和model.
Model
- Model为我们的数据模型,用于封装内部数据。比如在Note笔记本这个APP中,每一条笔记都有图片,内容和题目这些数据,那么我们就可以创造一个Node的Model类用于存储每一条笔记的数据。另外在创建一个Node的容器类NodeHolder,来管理所有的Node。这里Node和NodeHolder都是数据模型。
View - 注意这里的View不是我们Android控件里的View类。而要将其理解为用于展示我们data Model的表现层。比如对于一个通讯录来说,data Model为每个联系人的数据,那么View就是ListView中的每一个Item。Data Model和View是相互映射的关系,而连接二者的就是Presenter。
Presenter - The presenter sits between the model and view: it coordinates the UI with the data, ensuring they are in sync.
- 这里的P其实有点像MVC模式中的C,控制器。用于连接数据模型和数据表现层,使得二者能够同步变化。有点像ListView的Adapter。可以接受View层的操作来反馈给Model,也可以将Model的变化展现在View层。
第5节讲了关于MVP模式的最佳实践
- MVP的实践的核心要点是:将代码目录结构以功能来进行分包,即每一个相对独立的功能模块为一个package。
- 这样做的好处是:使得程序具有更高的可读性,模块性以及可测试性。
- 每一个功能模块的package下的代码以Model-View-Presenter的形式组织。见下图。
- Each feature package (shown in bold above) contains a Contract interface - this defines the interface for the View andPresenter callbacks of each feature.
-
每一个功能包中都包含一个Contract的接口其中定义了两个子接口:分别用于View和Presenter的回调。
各包下文件.png - 如上图,可以看出以下几点:
- 所有的数据模型放在/data包下
- 所有的工具类放在/util包下。这两个和之前开发的项目文件组织相同
- 每一个小的功能都放在一个独立的包下,view层和逻辑处理层的代码都位于包下。除此之外,还有一个后缀为Contract的接口用于连接View的类和presenter的类。
- NoteDetailContract 接口下有两个子接口:interface View和interface UserActionsListener 分别处理View层和presenter层。如图
注意:想学习MVP更多知识请参考其他文章。
- 选择proDebug运行程序,查看我们的测试效果:
- Open the Build Variants window and choose the prodDebug variant for your app module. (The option to open the Build Variants screen is on the lower, left hand side in Android Studio.)
Paste_Image.png
第6节:使用JUnit4 和 Mockito进行单元测试
基础概念:
- 单元测试:
- 单元测试是指测试的最小模块,通常指函数。
- 打包时单元测试的代码不会被编译进入APK中。
- Android中单元测试使用JUnit
- 与Java单元测试相同,Android单元测试也是维护代码逻辑的白盒工程,但由于Android运行环境的不同,Android单元测试的环境配置以及实施流程均有所不同。
-
Mockito:
在实际的工程项目中,类中必然存在各种依赖。若在单元测试时想要消除依赖,只测试待测试类相关的内容,或者依赖对象比较难拿到,此时可以使用Mockito框架mock出一个依赖对象。
注意:以上工具都需要添加依赖。
最佳实践
- 1.第一步:为我们的程序配置Test环境
- 在开始写测试程序之前需要为我们的Project配置Local Test的环境。
- 切换project的目录结构视图,Tests在src/下的test和androidTest目录下。我们会发现Android Studio已经自动为我们创建好了这两个文件夹。
- test包下为与Android环境无关的代码测试,androidTest为Android环境有关的代码测试,比如使用了Android的JDK。
补充知识:
如上下图所示:在project视角下的src/文件夹下,有test,AndroidTest,Main等若干个目录,根据Google文档的说法,每一个目录代表了一个不同的产品口味。我们定义了四种不同的文件集,用于不同编译和测试的流程,用于不同代码的测试,这样做使得我们开发测试变得简单了很多。
另外:所有的单元测试的代码都在test目录下。
Src下的文件目录.png
为我们的开发环境添加JUnit4的依赖:
<code>
dependencies {
// Required -- JUnit 4 framework
testCompile 'junit:junit:4.12' //01
// Optional -- Mockito framework
testCompile 'org.mockito:mockito-core:1.10.19' //02
}
</code>
解释:
- 01:依赖JUnit应该会最新版本,必须添加
- 02:依赖Mockito 框架,不是必选的
- 当项目中依赖的库较少的时候,用JUnit4进行本地单元测试已经足够,但是项目中若依赖较多的库的话需要使用Mockito框架来模拟,一般还是推荐加上Mockito的依赖。
添加完依赖后,就可以写测试用例了
比如需要测试一个是否为邮箱地址的方法是否正确:test/文件夹下代码如下
<pre>
import org.junit.Test;
import java.util.regex.Pattern;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
public class EmailValidatorTest {
@Test
public void emailValidator_CorrectEmailSimple_ReturnsTrue() {
assertThat(EmailValidator.isValidEmail("name@email.com"), is(true));
}
...
}
</pre>
- JUnit4采用注解的形式
- assertThat(),is()的语法
单元测试参考文档: