Android測試原理(二)

2.3. The Testing API(測試API)

Android的測試API是基於JUnitAPI和擴展的instrumentation 框架以及特定的Android測試類。

2.3.1. Junit

你可以使用TestCase類來做單元測試而不調用 Android的API。TestCase
AndroidTestCase類的父類,你可以用它來做Android依賴的對象。除瞭提供的JUnit框架,AndroidTestCase提供瞭Android特殊的建立,銷毀以及幫助方法。

你使用 Assert 類來展示測試的結果,assert比較值方法可以通過你期待的測試結果和實際的結果做比較並且拋出異常來判斷比較是否失敗。Android還提供瞭一個類的斷言,使得可以比較的類型更多,另一類的斷言用於進行UI測試。更多的詳細描述在 Assertion
classes

想要瞭解更多的東西關於JUnit,你可以在 junit.org 的主頁上閱讀到更多的文檔。值得註意的是Android的測試API支持的是JUnit3的代碼風格而不是JUnit4.你必須使用Android的測試運行器工具InstrumentationTestRunner來運行你的程序。這個測試類的描述文檔在Running
Tests

2.3.2.Instrumentation

Android的instrument是一系列的控制方法以及Android 系統自己設置的“鉤子”。這些鉤子能夠控制獨立的Android組件正常生命周期。他們也能控制怎麼樣加載Android運用程序。

正常情況下,Android的組件運行測生命周期是由系統決定的。例如,一個Activity對象的生命周期開始是由intent激活的。這個對象首先使用onCreat()調用,之後跟隨著onResume().當用戶開始另一個應用程序的時候會調用onPause()方法。如果這個Activity調用瞭finish()方法,則onDestroy()方法將會被調用。Android的運用框架層並沒有提供這些方法來直接的調用來調用這些函數,但是你可以使用instrumentation來實現這些功能。

同樣的,系統運行所有的組件在同一個進程。當然,你可以允許一些組件,像contentproviders 可以運行在不同的進程中,但是你不能強制一個應用程序強制和另一個已經在運行的應用程序在同一個進程當中運行。

使用Android的instrumentation,盡管你可以在你的測試代碼中調用你的這些方法。同樣可以讓你運行一步一步按照生命周期來運行組件,就好像你在調試組件一樣。

下面的這段代碼演示瞭怎麼保存和恢復Activity的狀態:

// 在測試環境下啟動Activity
    mActivity = getActivity();

    // 得到這個Activity中的主要UI句柄,一個Spinner   
 mSpinner = (Spinner)mActivity.findViewById(com.android.example.spinner.R.id.Spinner01);

    //獲取Spinner的位置 
    mActivity.setSpinnerPosition(TEST_STATE_DESTROY_POSITION);

    // Stop theactivity - The onDestroy() method should save the state of the Spinner 停止activity,調用onDestroy方法保存Spinner的狀態
    mActivity.finish();

    // Re-start theActivity - the onResume() method should restore the state of the Spinner重新啟動Activity,onResume()方法應該保存Spinner
    mActivity = getActivity();

    // Get theSpinner's current position 獲取Spinner的位置
    int currentPosition = mActivity.getSpinnerPosition();

    // Assert thatthe current position is the same as the starting position判斷當前的位置和啟動之前的位置是不是一樣的
    assertEquals(TEST_STATE_DESTROY_POSITION, currentPosition);

這裡關鍵的方法就是使用 getActivity(),它是instrumentation中的API的一部分。直到測試開始的時候才會調用這個方法。你可以提前設置測試的固件,這樣使得它能調用啟動時候的Activity.

同時,instrumentation能夠加載測試包和應用程序到相同的進程。因為它們測試組件和測試程序在同一個進程,測試能夠調用組件的方法,並且能夠修改檢測組件的字段。

Test case classes

Android提供瞭幾個測試用例類來擴展測試用例和斷言針對Android中的安裝,銷毀,和輔助方法。

AndroidTestCase

一個十分有用的測試類,特別是你開始進行Android的測試。它繼承自 TestCase 和Assert。它可以提供JUnit標準的setUp()方法和tearDown()方法,這對JUnit斷言方法是一樣的。除此之外,它提供的方法可以測試權限,一種防止內存泄露的類額度引用。

Component-specific test cases

在Android測試框架中一個主要的特征就是組件的測試類。這裡描述瞭特定組件的測試方法和固件安裝以及銷毀組件的生命周期的控制方法。他們同時也提供方法來建立模擬相應的對象。他們還提供瞭設置模擬對象的方法,這些測試主題:

·
Activity Testing

·
Content Provider Testing

·
Service Testing

Android沒有提供單獨的測試類給BroadcastReceiver。測試BroadcastReceiver通過測試Intent對象的組件,確認BroadcastReceiver是不是能夠正確響應正確。

ApplicationTestCase

你使用 ApplicationTestCase 測試類來啟動或者是銷毀APP。這些對象維護全局狀態信息,適用於一個應用程序的所有組件。這些測試用例能夠確認元素設置的正確性。註意,但是這個組件不允許你控制測試組件的應用程序包。

InstrumentationTestCase

如果你想使用instrumentation方法在測試用例類中,你必須使用InstrumentationTestCase或者其子類。Activity測試擴展瞭其父類的一些功能在判斷Activity測試時。

Assertion classes

因為Android的測試用例類繼承自JUnit,你可以使用斷言方法來展示出測試的結果。一個斷言的方法通過比較真實方法會和測試希望得到的值來拋出一個AssertionException如果對比測試失敗的話。使用斷言比日志記錄更加方便,並且提供更好的測試性能。

除瞭JUnit Assert 類方法,測試API同樣提供瞭 MoreAssertsViewAsserts 類:

MoreAsserts 它包含瞭很多強大的斷言例如: assertContainsRegex(String,
String)
能夠定期的展示出匹配

ViewAsserts 包含瞭很多有用的關於Views的斷言。例如它包含瞭 assertHasScreenCoordinates(View,
View, int, int)
如果View在屏幕上有一個很好的X和Y的坐標,它能夠簡單的測試幾何形狀和進行比對測試。

Mock object classes

為瞭方便依賴註入測試,Android提供瞭類能夠產生模擬系統的對象例如 Context類, ContentProvider 對象, ContentResolver 對象,
and Service 對象。一些測試同樣也提供瞭模擬Intent的對象。你使用這些模擬對象可是實現系統的某一部分的獨立測試或者是方便註入測試。這些類都在 android.test 和android.test.mock測試。Mock對象是一個獨立的測試和正在運行的系統是完全隔離的或者是覆蓋瞭正常的運行操作。例如,一個MockContentResolver 代替瞭正常的resolver框架使用自己的本地框架,能夠獨立於系統運行。

MockContentResolver 同樣也使用 notifyChange(Uri,
ContentObserver, boolean)
方法來觀察對象的外部環境是不是非偶然觸發的。

模擬類也有利於實現依附性註入通過提供一個非功能性的正常對象的子類來重新定義。例如, MockResources 提供一個子類 Resources所有的方法 在被調用的時候都會拋出一個異常,重寫的方法必須是提供信息的方法。

下面是在Android中可以使用的mock類:

MockApplication, MockContext, MockContentProvider, MockCursor, MockDialogInterface, MockPackageManager,
以及MockResources提供一個簡單並且有用的模擬策略。他們是獨立於相關系統的版本的類,並且所有的這些方法在調用的時候都會拋出 UnsupportedOperationException 當被調用的時候。為瞭使用他們,你重載的方法必須提供模擬依附。

註意:MockContentProviderMockCursor 中API的等級為8.

Resolver mock objects

MockContentResolver
提供瞭 獨立的測試contentprovider框架通過覆蓋正常的系統的resolver框架。不是在系統中找一個contentprovider給它付一個本地字符串,MockContentResolver使用他自己的內部表格。你必須明確的使用這個表格通過 addProvider(String,
ContentProvider)
.

Contexts for testing
上下文測試

Android提供瞭兩個有用的Context測試類:

l IsolatedContext
提供一個獨立的 Context, 文件,目錄以及數據庫操作,使用Context來產生一個測試區域。盡管這個功能是有限的,Context有足夠的樁代碼來回應系統調用。這些類允許你測試應用程序的數據操作,而不影響真是數據在設備上可能存在的裝置。l RenamingDelegatingContext
提供瞭一個Context其大部分的功能就是負責存在的Context,但是文件盒數據庫的操作是由 IsolatedContext
來單獨負責的。這些獨立的部分使用一個測試目錄並且產生一個特定的文件以及目錄的名字。你自己不能控制目錄的名字或者自己決定結構。這個對象提供瞭一種快速的方法來建立獨立的區域進行數據操作,保持其他的Context操作的正常性。

發佈留言