* 本篇文章已授权微信公众号 guolin_blog(郭霖)独家发布
本文预计阅读时间为15-20分钟
Android 测试简介
对于大多数 Android 商业项目,基本都是处于高速迭代的开发阶段,这个阶段不仅仅是对项目的开发效率,也对项目的产品质量提出了更高的要求。
通常大型项目都是通过黑盒测试等方式来提供质量相关的保障,但同时笔者认为也需要 Android 端的单元测试以及能自动在 Android 平台上运行的 UI 测试,这几种测试有以下几个优势:
- 更早发现代码中存在的 bug 等问题,提前 fix bug;
- 更好地设计:在进行项目重构的时候,保证重构的新代码能正确运行,这样就能在业务不断迭代的同时,更好地保障产品质量。
Android 测试代码位置
在 Android Studio 中新建新的项目时,它已自动为两种测试类型创建了对应的代码目录:
- 单元测试用例:位于 module-name/src/test/java 目录下,只依赖 JVM 环境而不需要 Android 环境
- InstrumentTest 测试/ UI 测试用例:位于 module-name/src/androidTest/java 目录下,在 Android 环境下才能运行
接下来,笔者将尝试为自己的项目(基于 MVP 架构开发)补充相应的单元测试用例和 UI 测试用例,来初步实践下如何在 Android 平台编写和运行相关的测试用例。
Android 单元测试实践
创建新用例
如果需要编写一个新的本地单元测试用例,只需打开你想测试的 java 代码文件,然后点击类名 – ⇧⌘T(Windows:Ctrl+Shift+T)-- 选择要生成的方法 – 选择 test 文件夹,对应于本地单元测试 – 完成。
增加依赖库
需要 JUnit 和 Mockito 框架支持,所以在 build.gradle 中增加:
testImplementation "junit:junit:4.12"
testImplementation "org.mockito:mockito-core:2.7.1"
编写测试代码
一般来说,编写一段测试代码需要三个步骤:
- 环境初始化
- 执行操作
- 验证结果正确性
笔者主要测试的是 MVP 架构中 P 层的代码。在笔者的项目中,P 层是通过 Dagger2 机制,注入一个 DataManager,也就是数据获取源。同时也需要一个 V 层的代理,这样在 P 层通过数据源获取数据之后,就能将数据交给 V 层,由 V 层去展示。
代码调用大致逻辑如下:
mPresenter = new NewsPresenter(mDataManager);
mPresenter.getNews();
mPresenter.attach(mView);
--> mView.showProgress(); // 在数据未加载完前加载进度条
--> mView.showNews(news);
--> mView.hideProgress(); // 在数据加载完后隐藏进度条
对应着,实际编写 P 层的单元测试用例的时候,并不需要一个真实的数据源,只需要通过 Mockito 框架,mock 出一个测试用的 DataManager 和 V 层代理。
对应着 Presenter 类,新创建的测试代码如下:
/**
* Created by Xu on 2019/04/05.
*
* @author Xu
*/
public class NewsPresenterTest {
@ClassRule
public static final RxImmediateSchedulerRule schedulers = new RxImmediateSchedulerRule();
@Mock
private NewsContract.View view;
@Mock
protected DataManager mMockDataManager;
private NewsPresenter newsPresenter;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
newsPresenter = new NewsPresenter(mMockDataManager);
newsPresenter.attach(view);
}
@Test
public void getNewsAndLoadIntoView() {
TencentNewsResultBean resultBean = new TencentNewsResultBean();
resultBean.setData(new ArrayList<>());
when(mMockDataManager.getNews()).thenReturn(Flowable.just(resultBean));
newsPresenter.getNews();
// 测试model是否有获取数据
verify(mMockDataManager).getNews();
// 测试view是否调用相应接口
verify(view).showProgress();
verify(view).showNews(anyL