android Instrumentation 轉載

?

Android提供了一系列強大的測試工具,它針對Android的環境,擴展了業內標準的JUnit測試框架。盡管你可以使用JUnit測試Android工程,但Android工具允許你為應用程序的各個方面進行更為復雜的測試,包括單元層面及框架層面。

Android測試環境的主要特征有:

l?? 可以訪問Android系統對象。

l?? Instrumentation框架可以控制和測試應用程序。

l?? Android系統常用對象的模擬版本。

l?? 運行單個test或test suite的工具,帶或不帶Instrumentation。

l?? 支持以Eclipse的ADT插件和命令行方式管理Test和Test工程。

這篇文章是對Android測試環境和測試方法的簡要介紹,并假設你已經擁有一定的Android應用程序編程及JUnit測試的經驗。

概要

Android 測試環境的核心是一個Instrumentation框架,在這個框架下,你的測試應用程序可以精確控制應用程序。使用Instrumentation, 你可以在主程序啟動之前,創建模擬的系統對象,如Context;控制應用程序的多個生命周期;發送UI事件給應用程序;在執行期間檢查程序狀態。 Instrumentation框架通過將主程序和測試程序運行在同一個進程來實現這些功能。

通過在測試工程的manifest文件中添 加<instrumentation>元素來指定要測試的應用程序。這個元素的特性指明了要測試的應用程序包名,以及告訴Android如何 運行測試程序。在Inustrumentation TestRunner章節有更多的細節描述。

下面的圖片概要的描述了Android的測試環境:



在 Android中,測試程序也是Android程序,因此,它和被測試程序的書寫方式有很多相同的地方。SDK工具能幫助你同時創建主程序工程及它的測試 工程。你可以通過Eclipse的ADT插件或者命令行來運行Android測試。Eclipse的ADT提供了大量的工具來創建測試用例,運行以及查看 結果。

Testing API

Android提供了基于JUnit測試框架的測試API來書寫測試用例和測試程序。另外,Android還提供了強大的Instrumentation框架,允許測試用例訪問程序的狀態及運行時對象。

下面的章節描述了Android中可利用的主要測試API。

JUnit TestCase類

繼 承自JUnit的TestCase,不能使用Instrumentation框架。但這些類包含訪問系統對象(如Context)的方法。使用 Context,你可以瀏覽資源,文件,數據庫等等。基類是AndroidTestCase,一般常見的是它的子類,和特定組件關聯。

子類有:

l?? ApplicationTestCase——測試整個應用程序的類。它允許你注入一個模擬的Context到應用程序中,在應用程序啟動之前初始化測試參數,并在應用程序結束之后銷毀之前檢查應用程序。

l?? ProviderTestCase2——測試單個ContentProvider的類。因為它要求使用MockContentResolver,并注入一個IsolatedContext,因此Provider的測試是與OS孤立的。

l?? ServiceTestCase——測試單個Service的類。你可以注入一個模擬的Context或模擬的Application(或者兩者),或者讓Android為你提供Context和MockApplication。

Instrumentation TestCase類

繼 承自JUnit TestCase類,并可以使用Instrumentation框架,用于測試Activity。使用Instrumentation,Android可 以向程序發送事件來自動進行UI測試,并可以精確控制Activity的啟動,監測Activity生命周期的狀態。

基類是InstrumentationTestCase。它的所有子類都能發送按鍵或觸摸事件給UI。子類還可以注入一個模擬的Intent。

子類有:

l?? ActivityTestCase——Activity測試類的基類。

l?? SingleLaunchActivityTestCase——測試單個Activity的類。它能觸發一次setup()和tearDown(),而不是每個方法調用時都觸發。如果你的測試方法都是針對同一個Activity的話,那就使用它吧。

l?? SyncBaseInstrumentation——測試Content Provider同步性的類。它使用Instrumentation在啟動測試同步性之前取消已經存在的同步對象。

l?? ActivityUnitTestCase——對單個Activity進行單一測試的類。使用它,你可以注入模擬的Context或Application,或者兩者。它用于對Activity進行單元測試。

不同于其它的Instrumentation類,這個測試類不能注入模擬的Intent。

l?? ActivityInstrumentationTestCase2——在正常的系統環境中測試單個Activity的類。你不能注入一個模擬的 Context,但你可以注入一個模擬的Intent。另外,你還可以在UI線程(應用程序的主線程)運行測試方法,并且可以給應用程序UI發送按鍵及觸 摸事件。

Assert類

Android還繼承了JUnit的Assert類,其中,有兩個子類,MoreAsserts和ViewAsserts:

l?? MoreAsserts類包含更多強大的斷言方法,如assertContainsRegex(String, String),可以作正則表達式的匹配。

l?? ViewAsserts類包含關于Android View的有用斷言方法,如assertHasScreenCoordinates(View, View, int, int),可以測試View在可視區域的特定X、Y位置。這些Assert簡化了UI中幾何圖形和對齊方式的測試。

Mock對象類

Android 有一些類可以方便的創建模擬的系統對象,如Application,Context,Content Resolver和Resource。Android還在一些測試類中提供了一些方法來創建模擬的Intent。因為這些模擬的對象比實際對象更容易使 用,因此,使用它們能簡化依賴注入。你可以在android.test和android.test.mock中找到這些類。

它們是:

l?? IsolatedContext——模擬一個Context,這樣應用程序可以孤立運行。與此同時,還有大量的代碼幫助我們完成與Context的通信。這個類在單元測試時很有用。

l?? RenamingDelegatingContext——當修改默認的文件和數據庫名時,可以委托大多數的函數到一個存在的、常規的Context上。使用這個類來測試文件和數據庫與正常的系統Context之間的操作。

l?? MockApplication,MockContentResolver,MockContext,MockDialogInterface,MockPackageManager,MockResources ——創建模擬的系統對象的類。它們只暴露那些對對象的管理有用的方法。這些方法的默認實現只是拋出異常。你需要繼承這些類并重寫這些方法。

Instrumentation TestRunner

Android 提供了自定義的運行測試用例的類,叫做InstrumentationTestRunner。這個類控制應用程序處于測試環境中,在同一個進程中運行測試 程序和主程序,并且將測試結果輸出到合適的地方。IntrumentationTestRunner在運行時對整個測試環境的控制能力的關鍵是使用 Instrumentation。注意,如果你的測試類不使用Instrumentation的話,你也可以使用這個TestRunner。

當 你運行一個測試程序時,首先會運行一個系統工具叫做Activity Manager。Activity Manager使用Instrumentation框架來啟動和控制TestRunner,這個TestRunner反過來又使用 Intrumentation來關閉任何主程序的實例,然后啟動測試程序及主程序(同一個進程中)。這就能確保測試程序與主程序間的直接交互。

在測試環境中工作

對Android程序的測試都包含在一個測試程序里,它本身也是一個Android應用程序。測試程序以單獨的Android工程存在,與正常的Android程序有著相同的文件和文件夾。測試工程通過在manifest文件中指定要測試的應用程序。

每個測試程序包含一個或多個針對特定類型組件的測試用例。測試用例里定義了測試應用程序某些部分的測試方法。當你運行測試程序,Android會在相同進程里加載主程序,然后觸發每個測試用例里的測試方法。

測試工程

為了開始對一個Android程序測試,你需要使用Android工具創建一個測試工程。工具會創建工程文件夾、文件和所需的子文件夾。工具還會創建一個manifest文件,指定被測試的應用程序。

測試用例

一個測試程序包含一個或多個測試用例,它們都繼承自Android TestCase類。選擇一個測試用例類取決于你要測試的Android組件的類型以及你要做什么樣的測試。一個測試程序可以測試不同的組件,但每個測試用例類設計時只能測試單一類型的組件。

一 些Android組件有多個關聯的測試用例類。在這種情況下,在可選擇的類間,你需要判斷你要進行的測試類型。例如,對于Activity來說,你有兩個 選擇,ActivityInstrumentationTestCase2和ActivityUnitTestCase。

ActivityInstrumentationTestCase2設計用于進行一些功能性的測試,因此,它在一個正常的系統環境中測試Activity。你可以注入模擬的Intent,但不能是模擬的Context。一般來說,你不能模擬Activity間的依賴關系。

相比而言,ActivityUnitTestCase設計用于單元測試,因此,它在一個孤立的系統環境中測試Activity。換句話說,當你使用這個測試類時,Activity不能與其它Activity交互。

作為一個經驗法則,如果你想測試Activity與Android的交互的話,使用ActivityInstrumentationTestCase2。如果你想對一個Activity做回歸測試的話,使用ActivityUnitTestCase。

測試方法

每 個測試用例類提供了可以建立測試環境和控制應用程序的方法。例如,所有的測試用例類都提供了JUnit的setUp()方法來搭建測試環境。另外,你可以 添加方法來定義單獨的測試。當你運行測試程序時,每個添加的方法都會運行一次。如果你重寫了setUp()方法,它會在每個方法運行前運行。相似 的,tearDown()方法會在每個方法之后運行。

測試用例類提供了大量的對組件啟動和停止控制的方法。由于這個原因,在運行測試之 前,你需要明確告訴Android啟動一個組件。例如,你可以使用getActivity()來啟動一個Activity。在整個測試用例期間,你只能調 用這個方法一次,或者每個測試方法一次。甚至你可以在單個測試方法中,調用它的finishing()來銷毀Activity,然后再調用 getActivity()重新啟動一個。

運行測試并查看結果

編譯完測試工程后,你就可以使用系統工具Activity Manager來運行測試程序。你給Activity Manager提供了TestRunner的名(一般是InstrumentationTestRunner,在程序中指定);名包括被測試程序的包名和 TestRunner的名。Activity Manager加載并啟動你的測試程序,殺死主程序的任何實例,然后在測試程序的同一個進程里加載主程序,然后傳遞測試程序的第一個測試用例。這個時 候,TestRunner會接管這些測試用例,運行里面的每個測試方法,直到所有的方法運行結束。

如果你使用Eclipse,結果會在JUnit的面板中顯示。如果你使用命令行,將輸出到STDOUT上。

測試什么?

除了一些功能測試外,這里還有一些你應該考慮測試的內容:

l?? Activity生命周期事件:你應該測試Activity處理生命周期事件的正確性。例如,一個Activity應該在pause或destroy事件 時保存它的狀態。記住一點的是屏幕方向的改變也會引發當前Activity銷毀,因此,你需要測試這種偶然情況確保不會丟失應用程序狀態。

l?? 數據庫操作:你應該確保數據庫操作能正確處理應用程序狀態的變化。使用android.test.mock中的模擬對象。

l?? 屏幕大小和分辨率:在發布程序之前,確保在所有要運行的屏幕大小和分辨率上測試通過。你可以使用AVD來測試,或者使用真實的目標設備進行測試。

附加:UI測試

接下來的章節為應用程序UI的測試提供了一些提示,特別是幫助你在UI線程里處理動作,觸屏和按鍵事件,和鎖屏。

UI線程中測試

Activity運行在程序的UI線程里。一旦UI初始化后,例如在Activity的onCreate()方法后,所有與UI的交互都必須運行在UI線程里。當你正常運行程序時,它有權限可以訪問這個線程,并且不會出現什么特別的事情。

當 你運行測試程序時,這一點發生了變化。在帶有instrumentation的類里,你可以觸發方法在UI線程里運行。其它的測試用例類不允許這么做。為 了一個完整的測試方法都在UI線程里運行,你可以使用@UIThreadTest來聲明線程。注意,這將會在UI線程里運行方法里所有的語句。不與UI交 互的方法不允許這么做;例如,你不能觸發Instrumentation.waitForIdleSync()。

如果讓方法中的一部分代碼運行在UI線程的話,創建一個匿名的Runnable對象,把代碼放到run()方法中,然后把這個對象傳遞給appActivity.runOnUiThread(),在這里,appActivity就是你要測試的app對象。

例如,下面的代碼實例化了一個要測試的Activity,為Spinner請求焦點,然后發送一個按鍵給它。注意:waitForIdleSync和sendKeys不允許在UI線程里運行:

? private MyActivity mActivity; // MyActivity is the class name of the app under test?

? private Spinner mSpinner;?



? ...?



? protected void setUp() throws Exception {?

????? super.setUp();?

????? mInstrumentation = getInstrumentation();?



????? mActivity = getActivity(); // get a references to the app under test?



????? /*?

?????? * Get a reference to the main widget of the app under test, a Spinner?

?????? */?

????? mSpinner = (Spinner) mActivity.findViewById(com.android.demo.myactivity.R.id.Spinner01);?



? ...?



? public void aTest() {?

????? /*?

?????? * request focus for the Spinner, so that the test can send key events to it?

?????? * This request must be run on the UI thread. To do this, use the runOnUiThread method?

?????? * and pass it a Runnable that contains a call to requestFocus on the Spinner.?

?????? */?

????? mActivity.runOnUiThread(new Runnable() {?

????????? public void run() {?

????????????? mSpinner.requestFocus();?

????????? }?

????? });?



????? mInstrumentation.waitForIdleSync();?



????? this.sendKeys(KeyEvent.KEYCODE_DPAD_CENTER);



關閉觸屏模式

為了控制從測試程序中發送給模擬器或設備的按鍵事件,你必須關閉觸屏模式。如果你不這么做,按鍵事件將被忽略。

關 閉觸摸模式,你需要在調用getActivity()啟動Activity之前調用 ActivityInstrumentationTestCase2.setActivityTouchMode(false)。你必須在非UI線程中運 行這個調用。基于這個原因,你不能在聲明有@UIThread的測試方法調用。可以在setUp()中調用。

模擬器或設備的解鎖

你可能已經發現,如果模擬器或設備的鍵盤保護模式使得HOME畫面不可用時,UI測試不能正常工作。這是因為應用程序不能接收sendKeys()的事件。避免這種情況最好的方式是在啟動模擬器或設備時關閉鍵盤保護模式。

你還可以顯式地關閉鍵盤保護。這需要在manifest文件中添加一個權限,然后就能在程序中關閉鍵盤保護。注意,你必須在發布程序之前移除這個,或者在發布的程序中禁用這個功能。

在<manifest> 元素下添加<uses-permission android:name=”androd.permission.DISABLE_KEYGUARD”/>。為了關閉鍵盤保護,在你測試的 Activity的onCreate()方法中添加以下代碼:

? mKeyGuardManager = (KeyguardManager)getSystemService(KEYGUARD_SERVICE);?

? mLock = mKeyGuardManager.newKeyguardLock("activity_classname");?

? mLock.disableKeyguard();

這里,activity_classname是Activity的類名。

轉載于:https://www.cnblogs.com/SZLLQ2000/p/4595943.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/458457.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/458457.shtml
英文地址,請注明出處:http://en.pswp.cn/news/458457.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Linker command failed with exit code 1(use -v to see invocation)

Linker command failed with exit code 1(use -v to see invocation) 出現這個問題的原因是&#xff1a;工程當中存在相同的文件&#xff0c;找到該文件將其刪除即可

【C#學習筆記】使用C#中的Dispatcher

form:https://www.jianshu.com/p/0714fc755988之前的文章說過了如何使用BackgroundWorker&#xff0c;今天要說的是WPF程序員處理多線程的另外一個方式 - Dispatcher當我們打開一個WPF應用程序即開啟了一個進程&#xff0c;該進程中至少包含兩個線程。一個線程用于處理呈現&…

流媒體 關鍵詞解釋

流媒體 流媒體是指采用流式傳輸的方式在網上播放的媒體格式, 是邊傳邊播的媒體&#xff0c;是多媒體的一種! 然后就是大家需要了解的幾個關鍵詞 幀:視頻是由很多連續圖像組成, 每一幀就代表一幅靜止的圖像 GOP:&#xff08;Group of Pictures&#xff09;畫面組&#xff0c;一個…

[C#] 等待啟動的進程執行完畢

from: https://www.cnblogs.com/qqhfeng/p/4769524.html有能有時候我們啟動了一個進程&#xff0c;必須等到此進程執行完畢&#xff0c;或是&#xff0c;一段時間&#xff0c; 關閉進程后再繼續往下走。Example sample1 等待應用程序執行完畢 //等待應用程序執行完畢private vo…

html body標簽

table table 屬性&#xff1a; border &#xff1a;定義表格的邊框寬度&#xff0c;默認為0&#xff0c;即無邊框。<table border"1"> title &#xff1a;表格的提示信息&#xff0c;當鼠標移到表格上方時&#xff0c;所提示的信息。 cellpadding &#xff1a;…

創建字符串的方法

//創建一個字符串常量 NSString *str"字符串"; //創建一個空的字符對象 NSString *str1[[NSString alloc]init];//實例方法 NSString *str2[NSString string];//類方法 //快速創建一個字符串 NSString *str3[[NSString alloc]initWithString:"字符串"];//實…

DataReceivedEventHandler 委托 接收調用執行進程返回數據

https://msdn.microsoft.com/zh-cn/library/azure/system.diagnostics.datareceivedeventhandler備注創建 DataReceivedEventHandler 委托時&#xff0c;需要標識將處理該事件的方法。 若要將事件與事件處理程序關聯&#xff0c;請將該委托的一個實例添加到事件中。 除非移除了…

coreData

CoreData使用 創建步驟流程 第一步先創建.xcdatamodeld文件&#xff08;New File -> iOS -> Core Data ->Data Model&#xff09; 屏幕快照 2016-07-07 下午10.40.16.png名字雖然可以任意取&#xff0c;但最好還是取和自己存儲數據庫名字一樣的名字。這樣可讀性更高些…

命令行下mysql新建用戶及分配權限

創建用戶&#xff1a; CREATE USER usernamehost IDENTIFIED BY password; 說明:username – 你將創建的用戶名, host – 指定該用戶在哪個主機上可以登陸,如果是本地用戶可用localhost, 如 果想讓該用戶可以從任意遠程主機登陸,可以使用通配符%. password – 該用戶的登陸密…

PetaPoco初體驗(轉)

PetaPoco初體驗&#xff08;轉&#xff09; PetaPoco初體驗&#xff08;轉&#xff09;大部分轉自&#xff1a; http://landyer.com/archives/138 PetaPoco C#微型ORM框架&#xff0c;基本無需配置&#xff0c;僅由單個cs文件構成&#xff0c;支持.net3.5 .net4.0。 截稿時Peta…

iOS當中的設計模式

代理模式 應用場景&#xff1a;當一個類的某些功能需要由別的類來實現&#xff0c;但是又不確定具體會是哪個類實現。 優勢&#xff1a;解耦合 敏捷原則&#xff1a;開放-封閉原則 實例&#xff1a;tableview的 數據源delegate&#xff0c;通過和protocol的配合&#xff0c…

c#的dllimport使用方法詳解

DllImport是System.Runtime.InteropServices命名空間下的一個屬性類&#xff0c;其功能是提供從非托管DLL&#xff08;托管/非托管是微軟的.net framework中特有的概念&#xff0c;其中&#xff0c;非托管代碼也叫本地&#xff08;native&#xff09;代碼。與Java中的機制類似&…

each函數循環數據表示列舉,列舉循環的時候添加dom的方法

var dotBox $(#bannerNum);var item <li></li>;var itemSize $(#bannerBack p).length;var dotBoxWidth itemSize*24;$(#bannerBack p).each(function () { dotBox.append(<li></li>); dotBox.find(li).eq(0).addClass(current);});這里要根…

使用lxml代替beautifulsoup

深入使用過lxml的都會深深地喜歡上它,雖然BeautifulSoup很流行,但是深入了解lxml后,你就再也不會使用bs了 我覺得beautifulsoup不好用,速度也慢(雖然可以使用lxml作為解析器了).另外soup.find_all這種簡直就是手工時代的操作(很多人使用find find_all這幾個函數, 其實它們使用起…

QT調用dll且進入DLL src code調試

qt應用程序AA.exe調用qt寫的BB.DLL時&#xff0c;進入BB.DLL src code調試 1、debug生成AA.exe 2、將debug生成的AA.exe整包debug folder放到BB.dll的debug生成的文件夾中 3、設置BB.dll這個project&#xff1a;項目----運行-----Executable中選擇BB.dll的debug文件夾中的AA.ex…

php安裝編譯時 configure: error: Cannot find OpenSSL's evp.h

yum install error: protected multilib versions errorsudo yum downgrade openssl 降級sudo yum install openssl-devel 另外參考yum install -y ncurses-devel yum install openssl openssl-develyum install openssl openssl-devel --setoptprotected_multilibfalse ln -s …

laravel項目中css樣式表的背景圖片不顯示

剛學laravel&#xff0c;遇到了很多坑&#xff0c;感覺laravel是挺強大的。 建好后臺項目&#xff0c;奈何css樣式表的背景圖片不顯示 .mainhd {background: url(../images/sky/body_bg.png) repeat-x 0px 0px; } 按理上面的寫法沒錯&#xff0c;因為是從別的后臺搬過來的&…

KVC KVO

1、KVC&#xff0c;即是指 NSKeyValueCoding&#xff0c;一個非正式的Protocol&#xff0c;提供一種機制來間接訪問對象的屬性。而不是通過調用Setter、Getter方法訪問。KVO 就是基于 KVC 實現的關鍵技術之一。 Demo&#xff1a; interface myPerson : NSObject { …

VS2010中 C++創建DLL圖解

一、DLL的創建 創建項目: Win32->Win32項目&#xff0c;名稱&#xff1a;MyDLL 選擇DLL (D) ->完成. 1、新建頭文件testdll.htestdll.h代碼如下&#xff1a;#ifndef TestDll_H_#define TestDll_H_#ifdef MYLIBDLL#define MYLIBDLL extern "C" _declspec(dllimp…

js理解 call( ) | apply( ) | caller( ) | callee( )

被js的這幾個方法搞的this暈頭轉向&#xff0c;下定決心搞清楚&#xff1b;1、call( )和apply( ):兩者都可以將函數綁定到另外一個對象上去運行&#xff0c;只是參數的傳遞方式不同&#xff0c;兩者都可以使當前函數擁有另一個對象的屬性和方法&#xff0c;實現js下的繼承&…