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

嗯哼,今天就講到這裏,博客我會繼續堅持寫下去,我會定期給大家分享一些開發技巧,以及優質的視頻教程
結束語

文中有講到不對的地方還請大家斧正。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章