配置测试环境
下载支持 Instrumented Unit Test 的支持包
具体就是查看 \Android\sdk\extras\android\m2repository\com\android\support\test 是否下载了这个 Test 包了
配置目录结构,AS 在某个未知版本开始就自动帮我们创建 Instrumented Unit Test 的目录结构了
自动生成的代码目录结构如下,如果
增加 dependencies,在 Module 的 build.gradle 中增加如下代码
androidTestCompile ‘com.android.support.test:runner:0.3’
androidTestCompile ‘com.android.support.test:rules:0.3’
androidTestCompile ‘org.hamcrest:hamcrest-library:1.1’
总结,在后来的测试中发现,Android Developer 的一堆配置都是过时的,在新版的 AS 和 Gradle 中,连条毛都不用配置。
编写测试代码
编写相关的 JUnit 4 test class 测试类
主要是理解测试原理和使用 Junit 4 test 测试的注解标签
被测试类,里面有个按钮,还有个 TextView ,点击按钮 TextView 更新按钮的点击次数
package com.wbiao.whistle.work;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
/**
* Created by Administrator on 2015/8/12.
*/
public class IActivity extends Activity implements View.OnClickListener{
private Button but;
private TextView tv;
public static int number = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_itest);
init();
}
private void init() {
but = (Button) findViewById(R.id.but_itest);
tv = (TextView) findViewById(R.id.tv_itest);
but.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch ((v.getId())){
case R.id.but_itest :
number++;
tv.setText(number+"");
break;
}
}
}
测试代码:继承 ActivityUnitTestCase 类
package com.wbiao.whistle.work;
import android.content.Intent;
import android.test.ActivityUnitTestCase;
import android.test.suitebuilder.annotation.MediumTest;
import android.widget.Button;
import android.widget.TextView;
import junit.framework.Assert;
/**
* Created by Administrator on 2015/8/12.
*/
public class IActivityTest2 extends ActivityUnitTestCase<IActivity> {
private Intent intent;
private Button but;
private TextView tv;
public IActivityTest2() {
super(IActivity.class);
}
@Override
protected void setUp() throws Exception {
super.setUp();
intent = new Intent(getInstrumentation().getTargetContext(),IActivity.class);
}
@MediumTest
public void testNull(){
startActivity(intent,null,null);
but = (Button) getActivity().findViewById(R.id.but_itest);
tv = (TextView) getActivity().findViewById(R.id.tv_itest);
assertNotNull(but);
assertNotNull(tv);
}
public void testClick(){
startActivity(intent,null,null);
IActivity activity = getActivity();
but = (Button) activity.findViewById(R.id.but_itest);
tv = (TextView) activity.findViewById(R.id.tv_itest);
for (int i = 0; i <10 ; i++) {
but.performClick();
}
int number = Integer.parseInt(tv.getText().toString());
assertTrue(10 == number);//正确行为
//assertSame(new String("10"), tv.getText().toString()); // 这里是报错,这里比较的应该是对象地址
assertSame("10", "10"); // 正确行为,字符串常量,用的是同一个对象引用
assertEquals("10", tv.getText().toString()); // 正确行为
assertNotNull("are you ok!", but);
//以上是 junit.framework 中
//接着是org.junit 这个框架是 junit.framework 中的扩张,其实 junit.framework 是Java 中的测试框架
// 在 assertThat 系列方法中会用到 hamcrest 框架中的匹配规则
// 这是一个简单的匹配demo
//org.junit.Assert.assertThat();
}
}
测试代码二:继承 ActivityInstrumentationTestCase2
package com.wbiao.whistle.work;
import android.content.Intent;
import android.test.ActivityInstrumentationTestCase2;
import android.test.TouchUtils;
import android.widget.Button;
import android.widget.TextView;
/**
* Created by Administrator on 2015/8/12.
*/
public class IActivityTest extends ActivityInstrumentationTestCase2<IActivity> {
//private IActivity activity;
//private Button but;
//private TextView tv;
public IActivityTest() {
super(IActivity.class);
}
@Override
protected void setUp() throws Exception {
super.setUp();
//Intent intent = new Intent(getInstrumentation().getTargetContext(),IActivity.class);
startActivity(intent,null,null);
//activity = getActivity();
//but = (Button) activity.findViewById(R.id.but_itest);
//tv = (TextView) activity.findViewById(R.id.tv_itest);
}
public void testClick() {
IActivity activity;
final Button but;
TextView tv;
activity = getActivity();
but = (Button) activity.findViewById(R.id.but_itest);
tv = (TextView) activity.findViewById(R.id.tv_itest);
/* for (int i = 0; i < 10; i++) {
TouchUtils.clickView(this, but);
//but.performClick();
}*/
//assertSame("0", tv.getText());
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
for (int i = 0; i <10 ; i++) {
but.performClick();
}
}
});
int in = Integer.parseInt(tv.getText().toString());
assertTrue(10==in);
}
@Override
protected void tearDown() throws Exception {
super.tearDown();
}
}
然后 在 AndroidMainfset 中添加权限说明,代码如下,注意官方给出的做法实在 test文件夹(可能你用的是 androidTest 文件夹)下新建一个 AndroidMainfset.xml 文件,然后在里面添加单元测试权限,在之前使用 Eclipse 中我们是直接在工程的 AndroidMainfset.xml 中添加单元测试的权限说明。
<instrumentation android:targetPackage="com.android.ut"
android:name="android.test.InstrumentationTestRunner"
android:label="Test Unit Tests">
</instrumentation>
// 这个标签意图不是很理解
<uses-library android:name="android.test.runner" />
根据 Test-Driven Development (TDD) 理论,开发软件的最佳方法,不是在你完成全部代码之后,为所有的代码编写单元测试代码,而是你在开发过程中,不断的实现一个新的功能,然后立马为它编写单元测试代码,所以开发就是一个不断迭代的过程。
关于在 Terminal 中执行单元测试(未确定,可忽略,这里只是做个标志)
gradlew cC
corresponding XML 和 generated HTML
/app/build/outputs/reports/androidTests/connected/