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();
    }
}

嗯哼,今天就讲到这里,博客我会继续坚持写下去,我会定期给大家分享一些开发技巧,以及优质的视频教程
结束语

文中有讲到不对的地方还请大家斧正。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值