序言
当程序业务逻辑也越来越复杂的时候,测试当中出了业务逻辑的bug是最难改了。如果说你有写单元测试的习惯,通过业务逻辑的单元测试可以很容易找到出错的代码块,然后解决掉。今天来给大家介绍下android中的单元测试基本使用
What android的单元测试可以干些什么事
android的framework中提供有关单元测试的api,首先我们先来看一下api的架构体系图
由此可以见系统已经支持 android中重要组件的单元测试(activity,Service,ContentProvider和Application)的单元测试
在实际工作当中可能对于业务逻辑测试和接口测试会偏多一些
比如mock一些业务流程 然后去写TODO伪代码,测试是否符合预期,然后去做UI实现。首先保证我们的业务逻辑不会出错,这样才能保证我们的程序不会出大的bug
How 如何使用
测试业务逻辑的单元测试
当测试不需要对app内部资源引用的时候,我们可以用org.junit.Test,此方式不会安装app到手机中
1.我们新建一个OperationServiceUnitTest
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.*;
/**
* Created by qinwei on 16/5/6 下午3:15
*/
public class OperationServiceUnitTest {
private OperationService service;
@Before
public void setUp() throws Exception {
// TODO 做一些测试配置
service=new OperationService();
}
@Test
public void testAdd() throws Exception {
assertEquals(1,service.add(1,1)) ;
}
@Test
public void testMultiplicative() throws Exception {
assertEquals(2,service.multiplicativ(1,1)) ;
}
@After
public void tearDown() throws Exception {
// TODO 测试结束调用
}
2.写一个方法testAdd 方法用@Test注解修饰
@Test
public void testAdd() throws Exception {
service=new OperationService();
//对测试结果做一个预期判断
assertEquals(2,service.add(1,1)) ;
}
测试通过后我们可以看到这个界面
测试不通过
当涉及到app内部资源的单元测试,此方式会安装app到手机中
1.创建AndroidTestCase子类
/**
* Created by qinwei on 16/5/6 下午3:48
*/
public class LoginTest extends AndroidTestCase {
public void testLogin() throws Exception {
String username = getContext().getString(R.string.username);
String password = getContext().getString(R.string.password);
LoginBiz biz = new LoginBiz();
assertEquals(true, biz.doLogin(username, password));
}
}
可用通过getContext方法拿到上下文对象,有了上下文我们就可以对数据库,sp操作,得到String.xml文件数据等等
-------------activity的单元测试待续------
activity的单元测试
可用来测试UI逻辑,比如模拟登录,用户输入校验,活动之间跳转
下面来看一个登录场景的单元测试
LoginActivity.java
public class LoginActivity extends AppCompatActivity implements View.OnClickListener {
private EditText mLoginUsernameEdt;
private EditText mLoginPasswordEdt;
private Button mLoginCommitBtn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mLoginUsernameEdt=(EditText) findViewById(R.id.mLoginUsernameEdt);
mLoginPasswordEdt=(EditText) findViewById(R.id.mLoginPasswordEdt);
mLoginCommitBtn=(Button) findViewById(R.id.mLoginCommitBtn);
mLoginCommitBtn.setOnClickListener(this);
}
@Override
public void onClick(View v) {
String uname=mLoginUsernameEdt.getText().toString();
String pwd=mLoginPasswordEdt.getText().toString();
Toast.makeText(LoginActivity.this, "uname:"+uname+",pwd "+pwd, Toast.LENGTH_SHORT).show();
}
}
LoginBiz.java
/**
* Created by qinwei on 16/5/6 下午3:50
*/
public class LoginBiz {
public boolean doLogin(String uname,String password){
//用的硬编码
return uname.equals("123456")&&password.equals("123456");
}
}
步骤:
1.创建ActivityInstrumentationTestCase2< T > 子类,这里的T指的是测试的activity类名
2.编写模拟用户操作的代码
/**
* Created by qinwei on 16/5/6 下午4:44
*/
public class LoginActivityTest extends ActivityInstrumentationTestCase2<LoginActivity>{
public LoginActivityTest(Class<LoginActivity> activityClass) {
super(activityClass);
}
public LoginActivityTest(){
super(LoginActivity.class);
}
private EditText mLoginUsernameEdt;
private EditText mLoginPasswordEdt;
private Button mLoginCommitBtn;
@Override
protected void setUp() throws Exception {
super.setUp();
LoginActivity activity=getActivity();
mLoginUsernameEdt=(EditText) activity.findViewById(R.id.mLoginUsernameEdt);
mLoginPasswordEdt=(EditText) activity.findViewById(R.id.mLoginPasswordEdt);
mLoginCommitBtn=(Button) activity.findViewById(R.id.mLoginCommitBtn);
}
public void testCheckInit() throws Exception {
assertNotNull(mLoginUsernameEdt);
assertNotNull(mLoginPasswordEdt);
assertNotNull(mLoginCommitBtn);
}
public void testInput() throws Exception {
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
mLoginUsernameEdt.requestFocus();//获取焦点
mLoginUsernameEdt.performClick();//模拟点击
}
});
/*由于测试用例在单独的线程上执行,所以此处需要同步application,
* 调用waitForIdleSync等待测试线程和UI线程同步,才能进行输入操作。
* waitForIdleSync和sendKeys不允许在UI线程里运行
*/
getInstrumentation().waitForIdleSync();
//调用sendKeys方法,输入用户名
sendKeys(KeyEvent.KEYCODE_P, KeyEvent.KEYCODE_H,
KeyEvent.KEYCODE_I, KeyEvent.KEYCODE_C,
KeyEvent.KEYCODE_O, KeyEvent.KEYCODE_M,
KeyEvent.KEYCODE_M);
getActivity().runOnUiThread(new Runnable()
{
@Override
public void run()
{
// TODO 获取焦点,模拟点击弹出输入法
mLoginPasswordEdt.requestFocus();
mLoginPasswordEdt.performClick();
}
});
//调用sendKeys方法,输入密码
sendKeys(KeyEvent.KEYCODE_1, KeyEvent.KEYCODE_2,
KeyEvent.KEYCODE_3, KeyEvent.KEYCODE_4);
}
public void testLogin() throws Exception {
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
mLoginCommitBtn.requestFocus();
mLoginCommitBtn.performClick();
int j=10;
try {
for (int i = 0; i < j; i++) {
Thread.sleep(400);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
@Override
protected void tearDown() throws Exception {
super.tearDown();
}
}
嗯哼,今天就讲到这里,博客我会继续坚持写下去,我会定期给大家分享一些开发技巧,以及优质的视频教程
结束语
文中有讲到不对的地方还请大家斧正。