單元測試簡介和使用

1. 單元測試的做用:

許多開發者都有個習慣,經常不樂意去寫個簡單的單元測試程序來驗證本身的代碼。對本身的程序一直很是有自信,或存在僥倖心理每次運行經過後就直接扔給測試組測試了。然而每次測試組的BUG提交過來後就會發現本身的程序還存在許多沒有想到的漏洞。可是每次修改好BUG之後仍是懷着僥倖心理,認爲此次不會有bug了。而後又一次自信地提交,結果又敗了。其實在項目開發的過程當中,實際編程的時間並非特別多,而真正耗時的每每是調試和修改階段。所以單元測試的覆蓋是頗有必要的。html

通常認爲,單元測試有四種做用:
(1)使代碼能夠放心修改和重構;
(2)迫使程序員從調用者而不是實現者的角度設計軟件模塊;
(3)迫使程序員將軟件模塊寫得易於測試和調用,從而有利於解耦;
(4)測試自己可做爲被測代碼的用法說明,從而替代了一部分文檔功能。 java

 

2. JUnit單元測試框架:

2.1. 簡介:

JUnit 是一個開源測試框架,用於編寫和運行可重複的自動化測試,讓咱們能夠確保咱們的代碼按預期工做。 JUnit 普遍應用於行業,能夠用做單獨的Java程序(在命令行)或在一個IDE如Eclipse內。 JUnit提供:android

  • 斷言測試預期結果.
  • 測試功能共享通用的測試數據.
  • 測試套件輕鬆地組織和運行測試.
  • 圖形和文本測試運行.

2.2. 簡單使用:

2.2.1 下載安裝

目前爲止最新的版本是JUnit4,不少IDE都會集成進去。若是沒有能夠下載這兩個包導入程序員

2.2.2.  JUnit的註釋

2.2.3. JUnit的斷言

2.2.4. 簡單示例

Caculate.java:編程

public class Caculate {
    int add(int numberA, int numberB){
        return numberA + numberB;
    }
}

 

 CaculateTest.java:框架

import static org.junit.Assert.assertEquals;

import org.junit.Before;
import org.junit.Test;

public class CaculateTest {
    
    private Caculate caculate;
    
    @Before
    public void init(){
        if(caculate == null){
            caculate = new Caculate();
        }
    }
    
    @Test
    public void testAdd(){
        int result = caculate.add(5, 3);
        assertEquals(8, result);
    }  
}

 

右鍵點擊CaculateTest.java的Run as --> JUnit Test:ide

 

3. Android中的單元測試

3.1. Android單元測試框架

Android基於JUnit專門寫了一套測試框架(Instrumented Test), 用於支持其單元測試和驗收測試.  類繼承關係:單元測試

3.2. 簡單示例

用這套框架能夠不使用JUnit的註解,直接在要測試的方法前面帶上test前綴就能夠。咱們按須要繼承這些基類就能夠編寫本身所須要的單元測試。Android studio的項目會自動生成一個src/androidTest/java文件夾,單元測試類就放在這個文件夾下面,目錄結構以下:測試

在src/main/java/com/junittest包下新建一個MainActivity.java, 裏面有一個按鈕和一個文本,點擊按鈕後能夠改變文本內容。spa

public class MainActivity extends Activity {

    private TextView mTextView;

    private Button mSubmitButton;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
    }

    private void initView() {
        mTextView = (TextView) findViewById(R.id.hello_text);
        mSubmitButton = (Button) findViewById(R.id.submit_button);
        mSubmitButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mTextView.setText("Change from Click!");
            }
        });
    }

    public String getTextString(){
        if(mTextView != null){
            return mTextView.getText().toString();
        }
        return "";
    }
}

 

在src/androidTest/javacom/junittest包下新建一個MainActivityTest.java, MainActivityTest繼承InstrumentationTestCase:

package com.junittest;

import android.content.Intent;
import android.test.InstrumentationTestCase;
import android.util.Log;
import android.widget.Button;
import android.widget.TextView;

/**
 * Created by caihanyuan on 15-10-28.
 */
public class MainActivityTest extends InstrumentationTestCase {

    final static String TAG = MainActivityTest.class.getName();

    private MainActivity mActivity;

    private TextView mTextView;

    private Button mButton;


    /**
     * 單元測試開始以前處理一些初始化工做
     * @throws Exception
     */
    @Override
    protected void setUp() throws Exception {
        Intent intent = new Intent();
        intent.setClassName("com.junittest", MainActivity.class.getName());
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        mActivity = (MainActivity) getInstrumentation().startActivitySync(intent);
        mTextView = (TextView) mActivity.findViewById(R.id.hello_text);
        mButton = (Button) mActivity.findViewById(R.id.submit_button);
    }

    /**
     * 單元測試結束後處理一些資源釋放工做
     * @throws Exception
     */
    @Override
    protected void tearDown() throws Exception {
        mActivity.finish();
        super.tearDown();
    }

    public void testInit() {
        assertNotNull(mActivity);
        assertNotNull(mTextView);
        assertNotNull(mButton);
    }

    public void testGetText() {
        String textString = mActivity.getTextString();
        assertEquals("Hello World!", textString);
    }

    public void testChangeText() {
        assertNotNull(mTextView);
        getInstrumentation().runOnMainSync(new Runnable() {
            @Override
            public void run() {
                mTextView.setText("ATest");
                assertEquals("ATest", mActivity.getTextString());
            }
        });
    }

    public void testClickButton(){
        assertNotNull(mButton);
        getInstrumentation().runOnMainSync(new Runnable(){
            @Override
            public void run() {
                mButton.performClick();
                assertEquals("Change from Click!", mActivity.getTextString());
            }
        });
    }

    public void testGetActivity() {
        Log.d(TAG, mActivity.getPackageName());
    }
}

測試結果:

因爲篇幅有限,這裏只是作簡單的介紹,Android測試框架的各個基類的用途能夠參考官網。

3.3. 單元測試框架Robolectric

Robolectric is a framework that allows you to write unit tests and run them on a desktop JVM while still using Android API. Robolectric mocks part of the Android framework contained in the android.jar file. This is similar to the unit test support via the Android Gradle plug-in but Robolectric provides also implementations for the methods while the Android unit testing support throws exceptions in all in android.jar methods which are used for unit testing.

所以Robolectric的設計目的是讓咱們能在本地JVM上直接進行Android的單元測試,這樣就不用等待Android真機或模擬器中打包,安裝,運行的過程。大大提升了單元測試的效率。

Robolectric的介紹和使用篇幅比較長,這裏就不寫出來了。參考文獻中附有相關的資料,感興趣的同窗能夠看看哦。

參考文獻:

單元測試的好處:http://www.blogjava.net/square/articles/158103.html

Junit官網: http://junit.org/

Android單元測試: http://developer.android.com/intl/zh-cn/training/activity-testing/index.html

Robolectric官網:http://robolectric.org/

相關文章
相關標籤/搜索