@ZeroGeek
2015-09-25T05:07:29.000000Z
字数 4991
阅读 773
每周主题
单元测试(unit testing),是指对软件中的最小可测试单元进行检查和验证。对于单元测试中单元的含义,一般来说,要根据实际情况去判定其具体含义,如C语言中单元指一个函数,Java里单元指一个类,图形化的软件中可以指一个窗口或一个菜单等。总的来说,单元就是人为规定的最小的被测功能模块。单元测试是在软件开发过程中要进行的最低级别的测试活动,软件的独立单元将在与程序的其他部分相隔离的情况下进行测试。
针对Android:
每次修改代码后需要重新编译,对于复杂的App,可能花费几分钟。极大浪费了时间,因此为了减少bug,提高代码质量,单元测试是十分被需要的。
举例,来测试下面的Activity,在EditText中输入字符,然后点击按钮,在TextView显示输入的字符。
public class FirstActivity extends Activity {
private static final String TAG = "FirstActivity";
@Bind(R.id.first_et)
EditText mEt;
@Bind(R.id.first_tv)
TextView mTv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_first);
ButterKnife.bind(this);
Log.d(TAG,"onCreate First");
}
@OnClick(R.id.first_btn)
public void setTextToView() {
mTv.setText(mEt.getText().toString());
}
//....
}
AndroidManifest.xml中添加权限与配置
在Application外加入
<uses-permission android:name="android.permission.RUN_INSTRUMENTATION" />
<instrumentation
android:name="android.test.InstrumentationTestRunner"
android:targetPackage="com.zero.androidtranningdemo" />
在Application内加入
<uses-library android:name="android.test.runner" />
之后所使用的测试库是自带的。
建议与上面文件夹一一对应
package com.zero.androidtranningdemo.activities;
import android.app.Instrumentation;
import android.test.ActivityInstrumentationTestCase2;
import android.test.TouchUtils;
import android.test.UiThreadTest;
import android.test.ViewAsserts;
import android.test.suitebuilder.annotation.MediumTest;
import android.test.suitebuilder.annotation.SmallTest;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import com.zero.androidtranningdemo.R;
/**
* Created by zero on 15-9-21.
*/
public class FirstActivityTest extends ActivityInstrumentationTestCase2<FirstActivity> {
// 构造函数是由测试用的Runner调用,用于初始化测试类的。
public FirstActivityTest() {
super(FirstActivity.class);
}
private Instrumentation mInstrumentation; // 我们可以将它理解为一种没有图形界面的,具有启动能力的,用于监控其他类(用Target Package声明)的工具类
private FirstActivity mActivity;
private TextView mTv;
private EditText mEt;
private Button mBtn;
/**
* setUp()方法是由测试Runner在其他测试方法开始前运行的。(必要)
* 1.调用父类构造函数,这是JUnit要求的。
* 2.初始化测试数据集的状态,具体而言:
* a.定义保存测试数据及状态的实例变量
* b.创建并保存正在测试的Activity的引用实例。
* c.获得想要测试的Activity中任何UI组件的引用。
*
* @throws Exception
*/
@Override
protected void setUp() throws Exception {
super.setUp();
// 把touch mode设置为真可以防止在执行编写的测试方法时,人为的UI操作获取到控件的焦点
// 确保在调用getActivity()方法前调用了setActivityInitialTouchMode
// setActivityInitialTouchMode(true);
mInstrumentation = getInstrumentation();
mActivity = getActivity();
mTv = (TextView) mActivity.findViewById(R.id.first_tv);
mEt = (EditText) mActivity.findViewById(R.id.first_et);
mBtn = (Button) mActivity.findViewById(R.id.first_btn);
}
/**
* 测试前提,检查测试数据集的设置是否正确,以及我们想要测试的对象是否已经正确地初始化。
*/
public void testPreconditions() {
assertNotNull("mActivity is null", mActivity);
assertNotNull("mTv is null", mTv);
assertNotNull("mEt is null", mEt);
assertNotNull("mBtn is null", mBtn);
}
/**
* 编写的测试方法
*/
// @UiThreadTest 可用于子线程处理
@MediumTest
public void testClickBtn() {
final String str = "Hello";
// 同步处理
mInstrumentation.runOnMainSync(new Runnable() {
@Override
public void run() {
mEt.setText(str); // 设置测试数据
mBtn.requestFocus(); // 得到焦点
mBtn.performClick(); // 模拟点击事件
assertEquals(str, mTv.getText().toString()); // 判断结果
}
});
// 如果不是Btn,其它View的点击可使用TouchUtils
// TouchUtils.clickView(this, mBtn);
}
/**
* 注意:TouchUtils辅助类提供与应用程序交互的方法可以方便进行模拟触摸操作。
* 我们可以使用这些方法来模拟点击,轻敲,或应用程序屏幕拖动View。
* <p/>
* 警告:TouchUtils方法的目的是将事件安全地从测试线程发送到UI线程。
* 我们不可以直接在UI线程或任何标注@UIThread的测试方法中使用TouchUtils这样做可能会增加错误线程异常。
*/
@SmallTest
public void testBtnLayout() {
final View decorView = mActivity.getWindow().getDecorView(); // 获取最上层的ViewGroup(FrameLayout)的引用
ViewAsserts.assertOnScreen(decorView, mBtn); // 检测一个view是否包含在Activity的根视图View中
}
/**
* @SmallTest 标志该测试方法是小型测试的一部分。
* @MediumTest 标志该测试方法是中等测试的一部分。
* @LargeTest 标志该测试方法是大型测试的一部分。
* 通常情况下,如果测试方法只需要几毫秒的时间,那么它应该被标记为@SmallTest,
* 长时间运行的测试(100毫秒或更多)通常被标记为@MediumTest或@LargeTest,
* 这主要取决于测试访问资源在网络上或在本地系统
*/
/**
* 垃圾清理与资源回收(非必要)
* @throws Exception
*/
@Override
protected void tearDown() throws Exception {
super.tearDown();
}
}
选定该文件,右键里 -》 Run “FirstAvtivityTest”
http://developer.android.com/intl/zh-cn/training/activity-testing/preparing-activity-testing.html (官网文档-英)
http://hukai.me/android-training-course-in-chinese/testing/activity-testing/activity-basic-testing.html (文档中文翻译)
http://baike.baidu.com/link?url=AQZm7w1QiYYnV64-oPjmi1xS9PyPhI3WAJW8j080EawuhFGbuWbLeWKmU9MLYflGsryjsRNe8ETf1xUwGGnyXK
http://www.cnblogs.com/AloneSword/p/4109407.html
http://www.cnblogs.com/tianzhijiexian/p/4296055.html
http://yelinsen.iteye.com/blog/977736
http://www.oschina.net/question/54100_27061