android 单元测试
序言
当程序业务逻辑也越来越复杂的时候,测试当中出了业务逻辑的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(); }}
嗯哼,今天就讲到这里,博客我会继续坚持写下去,我会定期给大家分享一些开发技巧,以及优质的视频教程
结束语
文中有讲到不对的地方还请大家斧正。
更多相关文章
- 自动 Android* 应用测试
- Android终端专项测试相关介绍
- 谈Android手机客户端的适配测试
- Android(安卓)渗透测试学习手册 第四章 对 Android(安卓)设备进
- Android中使用自身携带的Junit新建一个测试工程
- Android(安卓)Texting(2)Testing Fundamentals 测试基础篇
- android白盒测试所需其他安卓开发内容链接整理
- Android的单元测试
- android 跳动频谱 播放器(类似千千静听)