Android单元測试之JUnit
? ? ? ?隨著近期幾年測試方面的工作慢慢火熱起來。常常看見有招聘測試project師的招聘信息。在Java中有單元測試這么一個JUnit
方式,Android眼下主要編寫的語言是Java,所以在Android開發(fā)中也會有那么一個單元測試---JUnit。從Android的開發(fā)環(huán)境搭建可
以看出來,Android先要在JDK的基礎上,然后導入Android自己的SDK開發(fā)環(huán)境,當然Android的單元測試JUnit是專門測試Android
?APP里面的方法性能等。Android最常見的測試----JUnit。Android提供了一系列強大的測試工具,它針對Android的環(huán)境。擴展了
業(yè)內(nèi)標準的JUnit測試框架。
雖然你能夠使用JUnit測試Androidproject,但Android工具同意你為應用程序的各個方面進行更為復雜的
測試。包含單元層面及框架層面。
一、Android測試環(huán)境的主要特征有:
?1、能夠訪問Android系統(tǒng)對象。
?2、Instrumentation框架能夠控制和測試應用程序。
?3、Android系統(tǒng)經(jīng)常使用對象的模擬版本號。
?4、執(zhí)行單個test或test suite的工具,帶或不帶Instrumentation。
?5、支持以Eclipse的ADT插件和命令行方式管理Test和Testproject。
二、JUnit核心框架-----Instrumentation框架:
? ? ?Android測試環(huán)境的核心是一個Instrumentation框架,在這個框架下,你的測試應用程序能夠精確控制應用程序。使用Instrumentation。你能夠在主程序啟動之前,創(chuàng)建模擬的系統(tǒng)對象。如Context。控制應用程序的多個生命周期;發(fā)送UI事件給應用程序;在執(zhí)行期間檢查程序狀態(tài)。Instrumentation框架通過將主程序和測試程序執(zhí)行在同一個進程來實現(xiàn)這些功能。
? ? 通過在測試project的manifest文件里加入<instrumentation>元素來指定要測試的應用程序。這個元素的特性指明了要測試的應用程序包名,以及告訴Android怎樣執(zhí)行測試程序。?在Android中,測試程序也是Android程序。因此。它和被測試程序的書寫方式有非常多同樣的地方。
SDK工具能幫助你同一時候創(chuàng)建主程序project及它的測試project。
你能夠通過Eclipse的ADT插件或者命令行來執(zhí)行Android測試。Eclipse的ADT提供了大量的工具來創(chuàng)建測試用例。執(zhí)行以及查看結果。
? ? ? ?首先,我們來了解一下android的測試類的層次結構:
? ? ? ? ?
? ? ?Testing API
? ? ? ? ? Android提供了基于JUnit測試框架的測試API來書寫測試用例和測試程序。
另外,Android還提供了強大的Instrumentation框架。同意測試用例訪問程序的狀態(tài)及執(zhí)行時對象。
? ? JUnit TestCase類
? ? ? ? ? 繼承自JUnit的TestCase,不能使用Instrumentation框架。
但這些類包括訪問系統(tǒng)對象(如Context)的方法。使用Context。你能夠瀏覽資源,文件,數(shù)據(jù)庫等等。基類是AndroidTestCase,一般常見的是它的子類,和特定組件關聯(lián)。
? ? ??子類有:
? ? ? ??1、ApplicationTestCase——測試整個應用程序的類。它同意你注入一個模擬的Context到應用程序中,在應用程序啟動之前初始化測試參數(shù),并在應用程序結束之后銷毀之前檢查應用程序。
? ? ? ? 2、ProviderTestCase2——測試單個ContentProvider的類。
由于它要求使用MockContentResolver,并注入一個IsolatedContext。因此Provider的測試是與OS孤立的。
? ? ? ? 3、ServiceTestCase——測試單個Service的類。你能夠注入一個模擬的Context或模擬的Application(或者兩者),或者讓Android為你提供Context和MockApplication。
? ? Instrumentation TestCase類
? ? ? ? ?繼承自JUnit TestCase類,并能夠使用Instrumentation框架。用于測試Activity。
使用Instrumentation,Android能夠向程序發(fā)送事件來自己主動進行UI測試。并能夠精確控制Activity的啟動,監(jiān)測Activity生命周期的狀態(tài)。
基類是InstrumentationTestCase。
它的全部子類都能發(fā)送按鍵或觸摸事件給UI。子類還能夠注入一個模擬的Intent。
? ?子類有:
1、 ActivityTestCase——Activity測試類的基類。
2、 SingleLaunchActivityTestCase——測試單個Activity的類。它能觸發(fā)一次setup()和tearDown()。而不是每一個方法調(diào)用時都觸發(fā)。假設你的測試方法都是針對同一個Activity的話。那就使用它吧。
3、 SyncBaseInstrumentation——測試Content Provider同步性的類。
它使用Instrumentation在啟動測試同步性之前取消已經(jīng)存在的同步對象。
4、ActivityUnitTestCase——對單個Activity進行單一測試的類。
使用它。你能夠注入模擬的Context或Application,或者兩者。它用于對Activity進行單元測試。
不同于其他的Instrumentation類,這個測試類不能注入模擬的Intent。
5、 ActivityInstrumentationTestCase2——在正常的系統(tǒng)環(huán)境中測試單個Activity的類。
你不能注入一個模擬的Context。但你能夠注入一個模擬的Intent。
另外,你還能夠在UI線程(應用程序的主線程)執(zhí)行測試方法。而且能夠給應用程序UI發(fā)送按鍵及觸摸事件。
三、Instrumentation框架的測試使用方法
? ? ? ?Instrumentation和Activity有點類似,僅僅只是Activity是須要一個界面的。而Instrumentation并非這種,我們能夠?qū)⑺斫鉃橐环N沒有圖形界面的。具有啟動能力的,用于監(jiān)控其它類(用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);
? ?}
}
這個程序的功能比較簡單。點擊button之后,TextView的內(nèi)容由Hello變?yōu)镠ello Android.同一時候。在這個類中。我還寫了一個簡單的add方法。沒有被調(diào)用,僅供測試而已。
? ? ? 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());
? ?}
?
? ?/*
? ? * 模擬button點擊的接口
? ? */
? ?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()這個測試方法中。我模擬了一個button點擊事件。然后來推斷程序是否依照預期的運行。在這里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" />
? ? ? ? 經(jīng)過以上步驟,以下能夠開始測試了。測試方法也有以下幾種,以下介紹兩個經(jīng)常使用的方法:
? ? ? ?(1) 用Eclipse集成的JUnit工具
? ? ? ? ? ? ? ?在Eclipse中選擇projectSample,單擊右鍵。在Run as子菜單選項中選擇Android JUnit Test
? ??
同一時候能夠通過LogCat工具查看信息
?
? ? ? ? (2) 通過模擬器執(zhí)行單元測試
? ? ? ? ? ? 點擊模擬器界面的Dev Tools菜單
? ? ? ? ? ?再點擊Instrumentation選項。進入Instrumentation菜單
? ? ? ? ? ? ? ? ??
? ? ? ? ? 這里有一個InstrumentationTestRunner,它是測試的入口。點擊這個選項,就能夠自己主動執(zhí)行我們的測試代碼。下面為執(zhí)行結果:
? ? ? ?button點擊前
? ? ? ?button點擊后
??
至此,一個簡單的測試過程結束了。當然。android的測試內(nèi)容還有非常多,也有比較復雜的,我會在以后的學習過程中繼續(xù)分享我的體會。
好了。今天就到這里吧!
《新程序員》:云原生和全面數(shù)字化實踐50位技術專家共同創(chuàng)作,文字、視頻、音頻交互閱讀
總結
以上是生活随笔為你收集整理的Android单元測试之JUnit的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: setTimeOut函数和setInte
- 下一篇: Linux 模拟 鼠标 键盘 事件