文章目录
  1. 1. 什么是Instrumentation
  2. 2. 实现过程
    1. 2.1. 配置Manifest
    2. 2.2. 编写被测试的类
    3. 2.3. 编写测试类
    4. 2.4. 运行测试代码
    5. 2.5. 源码

之前学习过了monkey和monkeyrunner,这次来学习instrumentation。

什么是Instrumentation

Android测试环境的核心是一个Instrumentation框架,在这个框架下,你的测试应用程序可以精确控制应用程序。使用Instrumentation,你可以在主程序启动之前,创建模拟的系统对象,如Context;控制应用程序的多个生命周期;发送UI事件给应用程序;在执行期间检查程序状态。Instrumentation框架通过将主程序和测试程序运行在同一个进程来实现这些功能。

android instrumentation是android系统中一系列的控制方法或者钩子(hooks)。这些hooks可以脱离组件的正常生命周期控制一个android组件。它同样可以控制android如何加载应用程序。

实现过程

Instrumentation和Activity有点类似,只不过Activity是需要一个界面的,而Instrumentation并不是这样的,我们可以将它理解为一种没有图形界面的,具有启动能力的,用于监控其他类(用Target Package声明)的工具类。

配置Manifest

在manifest中添加如下配置

1
<instrumentation android:targetPackage="com.package.name" android:name="android.test.InstrumentationTestRunner" />

编写被测试的类

编写一个Activity,页面包含一个TextView,一个Button和一个Edittext。另外添加add()方法和isTrue()方法。

布局文件如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.ihongqiqu.instrumentationdemo.MainActivity">

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
android:id="@+id/tv_test"
android:layout_marginTop="47dp"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"/>

<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="test"
android:id="@+id/btn_test"
android:layout_below="@+id/tv_test"
android:layout_centerHorizontal="true"
android:onClick="onClick"
android:layout_marginTop="30dp"/>

<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/et_name"
android:layout_centerVertical="true"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
android:hint="Input your name"/>
</RelativeLayout>

Activity代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public class MainActivity extends AppCompatActivity {

private TextView tvTest;
private Button btnTest;
private EditText etName;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
this.etName = (EditText) findViewById(R.id.et_name);
this.btnTest = (Button) findViewById(R.id.btn_test);
this.tvTest = (TextView) findViewById(R.id.tv_test);
}

public void onClick(View view) {
if (BuildConfig.DEBUG) Log.d("MainActivity", "Test button clicked");
tvTest.setText("TEST");
}

public int add(int a, int b) {
return a + b;
}

public boolean isTrue(Boolean bool) {
return Boolean.TRUE == bool;
}

}

编写测试类

测试类实现对按钮点击,文本输入和对add()方法和isTrue()方法的测试,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
/**
* MainActivity测试类
*
* Created by zhenguo on 1/6/16.
*/
public class MainActivityTest extends InstrumentationTestCase {

private MainActivity mainActivity;
private Button btnTest;
private TextView tvTest;
private EditText etName;

@Override
protected void setUp() throws Exception {
super.setUp();
Intent intent = new Intent();
intent.setClassName(MainActivity.class.getPackage().getName(), MainActivity.class.getName());
// 必须添加FLAG_ACTIVITY_NEW_TASK这个flag
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mainActivity = (MainActivity) getInstrumentation().startActivitySync(intent);
tvTest = (TextView) mainActivity.findViewById(R.id.tv_test);
btnTest = (Button) mainActivity.findViewById(R.id.btn_test);
etName = (EditText) mainActivity.findViewById(R.id.et_name);
}

@Override
protected void tearDown() throws Exception {
mainActivity.finish();
super.tearDown();
}

public void testActivity() {
Log.d("MainActivityTest", "testActivity()");
getInstrumentation().runOnMainSync(new Runnable() {
@Override
public void run() {
btnTest.performClick();
}
});
SystemClock.sleep(3000);
assertEquals("TEST", tvTest.getText().toString());
}

public void testAdd() {
Log.d("MainActivityTest", "testAdd()");
int result = mainActivity.add(3, 5);
assertEquals(8, result);
}

public void testIsTure() {
Log.d("MainActivityTest", "testIsTure()");
assertTrue(mainActivity.isTrue(Boolean.TRUE));
assertFalse(mainActivity.isTrue(Boolean.FALSE));
assertFalse(mainActivity.isTrue(null));
}

public void testEditText() {
Log.d("MainActivityTest", "testEditText()");
mainActivity.runOnUiThread(new Runnable() {
@Override
public void run() {
etName.requestFocus();

}
});
SystemClock.sleep(2000);
// this.sendKeys("jingle1267");
getInstrumentation().sendStringSync("jingle1267");
SystemClock.sleep(2000);
assertEquals("jingle1267", etName.getText().toString());
}

}

运行测试代码

有两种方法运行测试,分别是:

  • IDE中右击 XXXTest.java 选择 Run ‘XXXTest’
  • 手机中选择 Dev Tools ,然后选择Instrumentation选项,然后选择 Test for you.package.name

源码

源码地址 https://github.com/jingle1267/AndroidTestDemo

如有任何问题,欢迎留言。


本文地址 http://94275.cn/2016/01/07/android-instrumentation/ 作者为 Zhenguo

author:Zhenguo
Author: Zhenguo      Blog: 94275.cn/     Email: jinzhenguo1990@gmail.com
I have almost 10 years of application development experience and have a keen interested in the latest emerging technologies. I use my spare time to turn my experience, ideas and love for IT tech into informative articles, tutorials and more in hope to help others and learn more.
文章目录
  1. 1. 什么是Instrumentation
  2. 2. 实现过程
    1. 2.1. 配置Manifest
    2. 2.2. 编写被测试的类
    3. 2.3. 编写测试类
    4. 2.4. 运行测试代码
    5. 2.5. 源码
返回顶部