Android單元測試之JUnit,androidjunit
隨著最近幾年測試方面的工作慢慢火熱起來,經常看見有招聘測試工程師的招聘資訊。在Java中有單元測試這麼一個JUnit
方式,Android目前主要編寫的語言是Java,所以在Android開發中也會有那麼一個單元測試---JUnit。從Android的開發環境搭建可
以看出來,Android先要在JDK的基礎上,然後匯入Android自己的SDK開發環境,當然Android的單元測試JUnit是專門測試Android
APP裡面的方法效能等。Android最常見的測試----JUnit。Android提供了一系列強大的測試載入器,它針對Android的環境,擴充了
業內標準的JUnit測試架構。儘管你可以使用JUnit測試Android工程,但Android工具允許你為應用程式的各個方面進行更為複雜的
測試,包括單元層面及架構層面。
一、Android測試環境的主要特徵有:
1、可以訪問Android系統對象。
2、Instrumentation架構可以控制和測試應用程式。
3、Android系統常用對象的類比版本。
4、運行單個test或test suite的工具,帶或不帶Instrumentation。
5、支援以Eclipse的ADT外掛程式和命令列方式管理Test和Test工程。
二、JUnit核心架構-----Instrumentation架構:
Android測試環境的核心是一個Instrumentation架構,在這個架構下,你的測試應用程式可以精確控制應用程式。使用Instrumentation,你可以在主程式啟動之前,建立類比的系統對象,如Context;控制應用程式的多個生命週期;發送UI事件給應用程式;在執行期間檢查程式狀態。Instrumentation架構通過將主程式和測試程式運行在同一個進程來實現這些功能。
通過在測試工程的manifest檔案中添加<instrumentation>元素來指定要測試的應用程式。這個元素的特性指明了要測試的應用程式套件組合名,以及告訴Android如何運行測試程式。 在Android中,測試程式也是Android程式,因此,它和被測試程式的書寫方式有很多相同的地方。SDK工具能協助你同時建立主程式工程及它的測試工程。你可以通過Eclipse的ADT外掛程式或者命令列來運行Android測試。Eclipse的ADT提供了大量的工具來建立測試案例,運行以及查看結果。
首先,我們來瞭解一下android的測試類別的階層:
Testing API
Android提供了基於JUnit測試架構的測試API來書寫測試案例和測試程式。另外,Android還提供了強大的Instrumentation架構,允許測試案例訪問程式的狀態及運行時對象。
JUnit TestCase類
繼承自JUnit的TestCase,不能使用Instrumentation架構。但這些類包含訪問系統對象(如Context)的方法。使用Context,你可以瀏覽資源,檔案,資料庫等等。基類是AndroidTestCase,一般常見的是它的子類,和特定組件關聯。
子類有:
1、ApplicationTestCase——測試整個應用程式的類。它允許你注入一個類比的Context到應用程式中,在應用程式啟動之前初始化測試參數,並在應用程式結束之後銷毀之前檢查應用程式。
2、ProviderTestCase2——測試單個ContentProvider的類。因為它要求使用MockContentResolver,並注入一個IsolatedContext,因此Provider的測試是與OS孤立的。
3、ServiceTestCase——測試單個Service的類。你可以注入一個類比的Context或類比的Application(或者兩者),或者讓Android為你提供Context和MockApplication。
Instrumentation TestCase類
繼承自JUnit TestCase類,並可以使用Instrumentation架構,用於測試Activity。使用Instrumentation,Android可以向程式發送事件來自動進行UI測試,並可以精確控制Activity的啟動,監測Activity生命週期的狀態。基類是InstrumentationTestCase。它的所有子類都能發送按鍵或觸摸事件給UI。子類還可以注入一個類比的Intent。
子類有:
1、 ActivityTestCase——Activity測試類別的基類。
2、 SingleLaunchActivityTestCase——測試單個Activity的類。它能觸發一次setup()和tearDown(),而不是每個方法調用時都觸發。如果你的測試方法都是針對同一個Activity的話,那就使用它吧。
3、 SyncBaseInstrumentation——測試Content Provider同步性的類。它使用Instrumentation在啟動測試同步性之前取消已經存在的同步對象。
4、ActivityUnitTestCase——對單個Activity進行單一測試的類。使用它,你可以注入類比的Context或Application,或者兩者。它用於對Activity進行單元測試。
不同於其它的Instrumentation類,這個測試類別不能注入類比的Intent。
5、 ActivityInstrumentationTestCase2——在正常的系統內容中測試單個Activity的類。你不能注入一個類比的Context,但你可以注入一個類比的Intent。另外,你還可以在UI線程(應用程式的主線程)運行測試方法,並且可以給應用程式UI發送按鍵及觸摸事件。
三、Instrumentation架構的測試用法
Instrumentation和Activity有點類似,只不過Activity是需要一個介面的,而Instrumentation並不是這樣的,我們可以將它理解為一種沒有圖形介面的,具有啟動能力的,用於監控其他類(用Target Package聲明)的工具類。
下面通過一個簡單的例子來講解Instrumentation的基本測試方法。
1.首先建立一個Android project,類名為Sample,代碼如下:
public class Sample extends Activity {
private TextView myText = null;
private Button button = null;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
myText = (TextView) findViewById(R.id.text1);
button = (Button) findViewById(R.id.button1);
button.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
myText.setText("Hello Android");
}
});
}
public int add(int i, int j) {
return (i + j);
}
}
這個程式的功能比較簡單,點擊按鈕之後,TextView的內容由Hello變為Hello Android.同時,在這個類中,我還寫了一個簡單的add方法,沒有被調用,僅供測試而已。
2. 在src檔案夾中添加一個測試包,在測試包中添加一個測試類別SampleTest
測試類別的代碼如下:
public class SampleTest extends InstrumentationTestCase {
private Sample sample = null;
private Button button = null;
private TextView text = null;
/*
* 初始設定
* @see junit.framework.TestCase#setUp()
*/
@Override
protected void setUp() {
try {
super.setUp();
} catch (Exception e) {
e.printStackTrace();
}
Intent intent = new Intent();
intent.setClassName("com.hustophone.sample", Sample.class.getName());
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
sample = (Sample) getInstrumentation().startActivitySync(intent);
text = (TextView) sample.findViewById(R.id.text1);
button = (Button) sample.findViewById(R.id.button1);
}
/*
* 垃圾清理與資源回收
* @see android.test.InstrumentationTestCase#tearDown()
*/
@Override
protected void tearDown() {
sample.finish();
try {
super.tearDown();
} catch (Exception e) {
e.printStackTrace();
}
}
/*
* 活動功能測試
*/
public void testActivity() throws Exception {
Log.v("testActivity", "test the Activity");
SystemClock.sleep(1500);
getInstrumentation().runOnMainSync(new PerformClick(button));
SystemClock.sleep(3000);
assertEquals("Hello Android", text.getText().toString());
}
/*
* 類比按鈕點擊的介面
*/
private class PerformClick implements Runnable {
Button btn;
public PerformClick(Button button) {
btn = button;
}
public void run() {
btn.performClick();
}
}
/*
* 測試類別中的方法
*/
public void testAdd() throws Exception{
String tag = "testAdd";
Log.v(tag, "test the method");
int test = sample.add(1, 1);
assertEquals(2, test);
}
}
下面來簡單講解一下代碼:
setUp()和tearDown()都是受保護的方法,通過繼承可以覆寫這些方法。
在android Developer中有如下的解釋
protected void setUp ()
Since: API Level 3
Sets up the fixture, for example, open a network connection. This method is called before a test is executed.
protected void tearDown ()
Since: API Level 3
Make sure all resources are cleaned up and garbage collected before moving on to the next test. Subclasses that override this method should make sure they call super.tearDown() at the end of the overriding method.
setUp ()用來初始設定,如啟動一個Activity,初始化資源等。
tearDown ()則用來垃圾清理與資源回收。
在testActivity()這個測試方法中,我類比了一個按鈕點擊事件,然後來判斷程式是否按照預期的執行。在這裡PerformClick這個方法繼承了Runnable介面,通過新的線程來執行類比事件,之所以這麼做,是因為如果直接在UI線程中運行可能會阻滯UI線程。
2.要想正確地執行測試,還需要修改AndroidManifest.xml這個檔案.
<!--用於引入測試庫-->
<uses-library android:name="android.test.runner" />
<activity android:name=".Sample" android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<uses-sdk android:minSdkVersion="3" />
<!--表示被測試的目標包與instrumentation的名稱。-->
<instrumentation android:targetPackage="com.hustophone.sample" android:name="android.test.InstrumentationTestRunner" />
經過以上步驟,下面可以開始測試了。測試方法也有以下幾種,下面介紹兩個常用的方法:
(1) 用Eclipse整合的JUnit工具
在Eclipse中選擇工程Sample,單擊右鍵,在Run as子功能表選項中選擇Android JUnit Test
同時可以通過LogCat工具查看資訊
(2) 通過模擬器運行單元測試
點擊模擬器介面的Dev Tools菜單
再點擊Instrumentation選項,進入Instrumentation菜單
這裡有一個InstrumentationTestRunner,它是測試的入口,點擊這個選項,就可以自動運行我們的測試代碼。以下為運行結果:
按鈕點擊前
按鈕點擊後
至此,一個簡單的測試過程結束了。當然,android的測試內容還有很多,也有比較複雜的,我會在以後的學習過程中繼續分享我的體會。好了,今天就到這裡吧!