最近接触到了第一个安卓项目,是关于安卓的接口测试的。于是呼一通找资料,看了五花八门的文章、文档,但是并没有非常适合的。
现在决定把学习的过程写下来,如果能帮到一两个跟我一样情况的就很开心了,开始学着记录学习笔记。
Android提供了一系列强大的测试工具,它针对Android的环境,扩展了JUnit测试框架。允许你为应用程序的各个方面进行更为复杂的测试,包括单元层面及框架层面。
Android测试工具包含几个包:android.test, android.test.mock, android.test.suitebuilder, 这里面最重要的包是android.test。
我们来看android.test 的包里面的类的关系:
可以看出这里面的类分两个体系,
androidTestCase 体系
继承自JUnit的TestCase,不能使用Instrumentation框架。但这些类包含访问系统对象(如Context)的方法。使用Context,你可以浏览资源,文件,数据库等等。基类是AndroidTestCase,一般常见的是它的子类,和特定组件关联。
子类有:
Instrumentation 体系
继承自JUnit TestCase类,并可以使用Instrumentation框架,用于测试Activity。使用Instrumentation,Android可以向程序发送事件来自动进行UI测试,并可以精确控制Activity的启动,监测Activity生命周期的状态。
基类是InstrumentationTestCase。它的所有子类都能发送按键或触摸事件给UI。子类还可以注入一个模拟的Intent。
子类有:
不同于其它的Instrumentation类,这个测试类不能注入模拟的Intent。
可以看这两个的区别, androidTestCase的适用于与activity无关的测试, 如程序逻辑, instrumentation适用于acitivity的测试。
先引用下网上的例子:
1.首先建立一个Android project,类名为Sample,代码如下:
package com.hustophone.sample; import android.app.Activity;import android.os.Bundle;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;import android.widget.TextView; public class Sample extends Activity { private TextView myText = null; private Button button = null; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); myText = (TextView) findViewById(R.id.text1); button = (Button) findViewById(R.id.button1); button.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { myText.setText("Hello Android"); } }); } public int add(int i, int j) { return (i + j); }}
这个程序的功能比较简单,点击按钮之后,TextView的内容由Hello变为Hello Android.同时,在这个类中,我还写了一个简单的add方法,没有被调用,仅供测试而已。
2. 在src文件夹中添加一个测试包,在测试包中添加一个测试类SampleTest
测试类的代码如下:
package com.hustophone.sample.test; import com.hustophone.sample.R;import com.hustophone.sample.Sample;import android.content.Intent;import android.os.SystemClock;import android.test.InstrumentationTestCase;import android.util.Log;import android.widget.Button;import android.widget.TextView; public class SampleTest extends InstrumentationTestCase { private Sample sample = null; private Button button = null; private TextView text = null; /* * 初始设置 * @see junit.framework.TestCase#setUp() */ @Override protected void setUp() { try { super.setUp(); } catch (Exception e) { e.printStackTrace(); } Intent intent = new Intent(); intent.setClassName("com.hustophone.sample", Sample.class.getName()); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); sample = (Sample) getInstrumentation().startActivitySync(intent); text = (TextView) sample.findViewById(R.id.text1); button = (Button) sample.findViewById(R.id.button1); } /* * 垃圾清理与资源回收 * @see android.test.InstrumentationTestCase#tearDown() */ @Override protected void tearDown() { sample.finish(); try { super.tearDown(); } catch (Exception e) { e.printStackTrace(); } } /* * 活动功能测试 */ public void testActivity() throws Exception { Log.v("testActivity", "test the Activity"); SystemClock.sleep(1500); getInstrumentation().runOnMainSync(new PerformClick(button)); SystemClock.sleep(3000); assertEquals("Hello Android", text.getText().toString()); } /* * 模拟按钮点击的接口 */ private class PerformClick implements Runnable { Button btn; public PerformClick(Button button) { btn = button; } public void run() { btn.performClick(); } } /* * 测试类中的方法 */ public void testAdd() throws Exception{ String tag = "testAdd"; Log.v(tag, "test the method"); int test = sample.add(1, 1); assertEquals(2, test); }}
下面来简单讲解一下代码:
setUp()和tearDown()都是受保护的方法,通过继承可以覆写这些方法。
在android Developer中有如下的解释
protected void setUp ()
Since: API Level 3
Sets up the fixture, for example, open a network connection. This method is called before a test is executed.
protected void tearDown ()
Since: API Level 3
Make sure all resources are cleaned up and garbage collected before moving on to the next test. Subclasses that override this method should make sure they call super.tearDown() at the end of the overriding method.
setUp ()用来初始设置,如启动一个Activity,初始化资源等。
tearDown ()则用来垃圾清理与资源回收。
在testActivity()这个测试方法中,我模拟了一个按钮点击事件,然后来判断程序是否按照预期的执行。在这里PerformClick这个方法继承了Runnable接口,通过新的线程来执行模拟事件,之所以这么做,是因为如果直接在UI线程中运行可能会阻滞UI线程。
2.要想正确地执行测试,还需要修改AndroidManifest.xml这个文件.
<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.hustophone.sample" android:versionCode="1" android:versionName="1.0"> <application android:icon="@drawable/icon" android:label="@string/app_name"> <!--用于引入测试库--> <uses-library android:name="android.test.runner" /> <activity android:name=".Sample" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> <uses-sdk android:minSdkVersion="3" /> <!--表示被测试的目标包与instrumentation的名称。--> <instrumentation android:targetPackage="com.hustophone.sample" android:name="android.test.InstrumentationTestRunner" /></manifest>
经过以上步骤,下面可以开始测试了。测试方法也有以下几种,下面介绍两个常用的方法:
(1) 用Eclipse集成的JUnit工具
在Eclipse中选择工程Sample,单击右键,在Run as子菜单选项中选择Android JUnit Test
(2) 使用Intellij IDEA 或者Android studio
右键点击你的测试工程,或者测试类, 选择Run,然后选择机器人图标的那个选项,窗口和Eclipse的差不多, 同样使用LogCat查看信息。