开始的开始
最近在做Android上的自动化测试,从最初的第三方自动化测试框架appium到后来的Android Support Testing Library,再到最终完成答疑君Android客户端一些核心流程的自动化测试,期间也是经历了各种大大小小的坑。这个系列的文章也是想通过描述整个探索道路来记录一下整个Android自动化测试的入门过程,同时也采用了我自己所喜欢的step by step的模式来介绍整个流程,以便大家可以很快地操作起来。
但是,在开始的开始,我认为每一种语言或者特性可能在不同的环境中都有不同的实现方式,所以有必要在此贴上我的一些开发环境以作参考:IDE: Android StudioAndroid SDK: API Level 23gradle version: 2.8build tool version: 23.0.2测试环境:真机(Nexus 6 with Android 6.0.1; MIUI phones若干)入门之前
曾经和gemini聊到机器人统治地球的问题(这好像是异教徒们的愿景orz...),后来想了想自动化测试这个东西其实也是,让机器去模仿人的行为,让它自己去统治整个测试工作。既然是去模仿人的行为,那实际上也应该认为机器只能理解人所能理解的东西。比方说,当我去人为地做一些测试的时候,我所期待的只是UI上的变化可以符合我的预期,至于它背后的数据是怎样的实际上我并不care。因此,在做自动化测试时我个人有个最基本的思路:
把自己当成用户,只关注我能看到的东西。
Start from Gradle
好了!终于可以开始了!既然是采用Gradle进行Android工程的构建,那自然是少不了Gradle的配置啦!根据官方文档的说明,我们首先需要在我们工程的build.gradle中添加如下配置:
android { defaultConfig { testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" }}
这里实际上只做了一件事情,就是为我们的工程指定一个TestInstrumentationRunner,TestInstrumentationRunner是用来跑我们所写的所有的测试用例的。当我们采用test的模式来构建工程时,这个Runner便会自动为我们执行所有的的测试用例,并且返回相应的测试结果。
另外,我们还需要在build.gradle中增加instrumentation testing所需要的依赖:dependencies { androidTestCompile 'com.android.support:support-annotations:23.1.1' androidTestCompile 'com.android.support.test:runner:0.4.1' androidTestCompile 'com.android.support.test:rules:0.4.1'}
Where am I?
好了!我们现在有工具来跑测试了,接下来只要添加我们的测试用例了!于是问题来了,我们应该在哪里添加测试用例呢?
如果你在Android Studio中新建一个工程,会发现在src目录下,和main平行的还有一个androidTest目录。一般而言,我们将工程代码放在src/main/java目录下,将与之相关的测试代码放在src/androidTest/java目录下。如下所示:src/ androidTest/java ----这里存放instrumentation test相关的代码 main/java ----这里存放工程代码
同时,为了让工程更容易维护,建议将相应Class的测试代码放到相同名称的包下面,比如,在Package-name下面有一个Class A:
src/main/java/package-name/A.java
那么,建议将A的测试类放到androidTest下面对应的路径下:
src/androidTest/java/package-name/ATest.java
可以Say Hello了!
好了!我要开始变身了!下面我们要向testing的世界say hello了!
我在package-name/module/main包下面有一个AppStartActivity,作为答疑君的启动页。在这个启动页上会显示一段文字,我希望通过自动化测试来确认这个文字确实显示在了屏幕上。于是,我应该在androidTest/package-name/module/main下面创建一个AppStartActivityTest类,键入如下代码:
package im.dayi.app.student.module.main;import android.support.test.InstrumentationRegistry;import android.support.test.runner.AndroidJUnit4;import android.test.ActivityInstrumentationTestCase2;import android.widget.TextView;import org.junit.After;import org.junit.Before;import org.junit.Test;import org.junit.runner.RunWith;/** * Test for AppStartActivity * Created by Anchorer on 2016/1/13. */@RunWith(AndroidJUnit4.class)public class AppStartActivityTest extends ActivityInstrumentationTestCase2{ private AppStartActivity mActivity; private TextView mContentView; public AppStartActivityTest() { // 所有的ActivityInstrumentationTestCase2子类都需要调用该父类的super(String)构造方法 super(AppStartActivity.class); } @Before public void setUp() throws Exception { super.setUp(); // @Before注解表示在执行所有的testCase之前要做的事情 injectInstrumentation(InstrumentationRegistry.getInstrumentation()); // getActivity()方法会在开始所有的testCase之前启动相应的Activity mActivity = getActivity(); // findViewById()很熟悉吧?找到我要测试的控件 mContentView = (TextView) mActivity.findViewById(R.id.welcome_content); } @Test public void testPreconditions() { // @Test注解表示一个测试用例方法 assertNotNull("AppStartActivity is null", mActivity); } @Test public void testContentDisplayed() { // 这里就是我们测试的目标,判断目标控件的text不为空 String content = mContentView.getText().toString(); assertNotNull("AppStartActivity Content is Null", content); }}
相关代码的说明请见注释。
接下来,我要开始跑这个测试用例了。首先,打开Android Studio的Build variants窗口,将Test Artifact设为Android Instrumentation Tests,然后Synchronize一下工程,会看到androidTest路径下的背景颜色变成了绿色。
此时,在AppStartActivityTest.java点击菜单,选择Run 'AppStartActivityTest...',就可以从控制台看到测试已经在跑了:
从控制台的日志来看,整个测试过程初期,会向测试设备安装两个APK:APP APK和test APK。整个测试结束之后,会看到测试结果:
以上测试结果说明,所有test case全部测试通过。
好了!这就是整个自动化测试的大体流程了!接下来我已经迫不及待地想要把Android强大的自动化测试提供的特性分享出来了!!