史上最簡單Robotium跨進程操作實踐——基於ADB架構,robotiumadb

來源:互聯網
上載者:User

史上最簡單Robotium跨進程操作實踐——基於ADB架構,robotiumadb

樓主原創,分享不易,轉載請註明出處,謝謝。


Robotium是Android平台下一款非常優秀的自動化測試架構,它做android平台自動化的優勢想必看到這篇文章的人應該都很清楚。但優點歸優點,缺點也比較多,最明顯的缺點有兩個,一是必須要和被測系統簽名保持一致,二是不能做任何跨進程的操作。

 

很多小夥伴知道怎麼用robotium,也知道它有這些限制,但不知道其中的原因。這裡簡單地說一下,robotium的這些先天不足的主要原因是由於它本身是基於instrumentation機制的,這既有好處也有壞處。好處是通過instrumentation注入到被測進程,從而與被測進程運行在同一進程空間,使得它能夠非常方便地識別被測應用中的被測對象,並對這些對象進行操作。壞處是既然robotium已經跟被測應用”合體”了,那麼根據android的進程隔離機制,它自然也被系統隔離在其他進程之外,無法跨進程操作任何對象,(1)所示。

 

圖(1)Android進程沙箱

 

其實使用相同的簽名對於單應用的測試來說並不是難事,網上有很多應用重簽名的方法和工具供大家使用。但不能跨進程操作確實成為了robotium最大的軟肋,很多第三方的應用測試或多或少都有一些跨進程操作的測試情境,所以不少人因為這個問題而放棄了robotium,甚是可惜啊。

 

作為robotium的鐵杆粉之一(我最開始接觸android自動化測試就是用的robotium),斷斷續續用了好幾年,一直覺得是android平台最好用的自動化測試載入器之一。對於robotium怎樣突破進程的限制也做過一些研究,網上比較多的解決方案無外乎有以下幾種:

1. 自己寫服務做server,基於AIDL或編寫socket與monkeyserver進行通訊,然後在robotium測試指令碼裡調用介面方法來間接地進行跨進程的操作,這種方式可以參考下這篇文章的例子:http://www.robotium.cn/archives/584。文章的作者只是給出了思路,我自己曾經按照這種方法去實現過,發現該方法的優勢是比較穩定,缺點就是實現起來確實比較複雜,而且有些操作無法找到現成的系統aidl介面來進行操作,比如調用拍照操作,所以其執行個體子並不是很多,技術上的局限性較大。

2. 基於廣播和service服務。這種方法的實現方式可以參考http://www.ltesting.net/ceshi/open/kygncsgj/2013/0507/206229.html這篇文章的描述。這種方法我沒有親自去試過,但不難發現這種方法原理稍微簡單些,但該方法貌似需要系統簽名,而且自己寫廣播和服務來調用系統api,難度也不算小,所以一般不建議使用這種方式。

 

綜合上面的這些跨進程的解決方案,其實都感覺不太理想,對於很多初學者來說不是太難實現就是局限性比較大,一直沒有找到一個比較理想的解決方案。直到後來在testerhome上看到一個技術很牛的兄弟把常用的adb命令做了一個很完備的封裝(PS:真的是很全了,至少常用的adb命令都在,我甚至之前都沒有想過adb命令還能做這麼多事情),做成了一個獨立的測試協助工具輔助。我就突然聯想到為何不能使用adb命令來輔助robotium進行跨進程操作呢?既然該架構已經封裝了基於adb的所有操作,而且adb又是不受系統限制的,那麼基於這個架構理論上進行跨進程操作是沒有任何問題的。後來經過實驗,確實效果不錯,輕量級、操作簡單、使用方便,並且輕鬆跨進程,真是居家測試、屌絲逆襲的必備神器啊。好了,閑話不多說了,接下來我們就來詳細地看看究竟是怎麼用的。

 

先來簡單地介紹下這個adb命令架構的常用介面。這個架構裡有三個主要的包,分別介紹如下:

 

xuxu.autotest這個包裡面主要有兩個類,一個是AdbDevice,封裝了功能測試中常用的一些操作,如擷取當前activity的名稱和包名、擷取裝置解析度、關閉應用、點擊對象等常用功能,非常實用。另一個類是XuImage,顧名思義,即封裝了一些常見的圖片操作,如得到指定邊界的圖片、對比圖片是否一致、截取圖片等。

 

xuxu.autotest.element這個包主要用於擷取被測對象,主要是封裝了一個Position對象,用於通過Class Name、Id、Contentdesc等屬性來擷取一個被測對象,其底層是通過uiautomator來dump 當前ui的xml檔案的,可以擷取到所有對象節點的xml檔案。

 

xuxu.autotest.utils這個包裡面主要提供了對Date日期時間的操作,ImageUtil對圖片的操作及Regex和shell語句的操作的封裝,方便大家的使用。總的來說整個架構的介面設計還是非常齊全的,可以實現很多常用功能,具體功能大家可以自己看源碼和協助文檔來摸索。

 

接下來就進入我們本次的主題——跨進程。為了方便大家理解,我會在本文中選擇兩個非常常見的跨進程操作環境來說明如何跨進程,也就是大家喜聞樂見的相機拍照打電話來進行示範。

 

例子1、跨進程操作之相機拍照。

被測程式非常簡單,程式介面如(2)所示:


圖(2)

 

點擊第一個介面的“拍照片”按鈕後,進入介面2,點擊其中的“拍張照片”後啟動系統的相機,當使用者按下拍照功能鍵後,系統可以將使用者拍下的照片顯示在應用中,以備後續瀏覽或者是上傳。由於相機應用和我們所寫的被測應用是兩個不同的應用,所以這就屬於典型的跨進程操作,Robotium架構本身是無法對這個相機介面進行操作的。

 

接下來看看關鍵的測試工程怎麼建立的。測試工程的建立方法非常簡單,操作步驟如下:

1. 首先按照常規的android測試工程的建法,建立一個常規測試工程。

2. 在工程中引入robotium和adbForAndroid的jar包。

這樣,我們的測試工程就準備好了。

接下來的步驟就是寫測試指令碼。由於AdbForAndroid架構是按照元素的相關屬性來尋找並定位被測對象的,所以首先要弄清楚我們要操作的跨進程的介面上的對象的資訊,這些資訊我們可以通過很多現成工具來看,我這裡選擇android內建的uiautomatorviewer。先在模擬器上手工開啟被測程式,進入拍照的相機介面,並用uiautomatorviewer查看介面元素資訊如(3)所示:


圖(3)

 

我們可以看到,我們要點擊的拍照按鈕的屬性在圖(3)的右下角的列表中已全部展現出來。那麼我們該選哪個呢?這個問題取決於adbForAndroid架構支援由哪些屬性來擷取元素。通過查詢其協助文檔,我們知道目前這個架構中常用的尋找元素的方法如下:

  • findElementByContentdesc
  • findElementByClass
  • findElementByText
  • findElementById

由於我現在使用的模擬器版本為4.2.2,所以uiautomatorviewer無法顯示id屬性,如果大家用的是4.3版本以上,就可以看到元素的id屬性了。

 

那麼現在這種情況來看,我們最好就選擇Contentdesc屬性來定位對象了。代碼很簡單,如下:

Element element =position.findElementByContentdesc("Shutter button");adbDevice.tap(element);  //點擊拍照按鈕

好,接下來點擊了拍照按鈕之後,拍照功能還會讓你選擇是確定還是取消操作,如(4)所示:


圖(4)

那麼如法炮製,我們通過查詢獲知,這個用於確定的“√”按鈕,它的屬效能用於定位的其實只有class屬性。不過這裡要注意的是,此時由於我們用的是class屬性,大家可以看到介面上class屬性跟我們要點擊的“√”這個按鈕相同的對象很多,所以我們必須用findElementsByClass方法了。這個方法返回的是一個ArrayList<Element>,所以我們可以寫如下的代碼來擷取所有class屬性為”android.widget.ImageView”的元素列表。

ArrayList<Element> imageViews =position.findElementsByClass("android.widget.ImageView");

好,寫完之後,現在問題來了,究竟這個數組裡面哪個index才是對應的我們要點擊的“√”按鈕呢?經過實驗,我發現介面上多個相同元素返回到數組中時,對應元素位置是按照介面上的位置從上到下、從左至右來的,所以我們要點擊的這個按鈕的index應該是4。所以點擊它的代碼如下:

adbDevice.tap(imageViews.get(4));    //2是x,3是重拍,4是√

上面的代碼運行完後,介面就會回到我們的被測程式,後面的操作就不用我再多說了,大家看看是不是非常簡單?

 

例子2、跨進程操作之打電話

有了第一個例子的基礎,其實第二個例子就很好實現了。被測程式非常簡單,如(5)所示:


圖(5)

點擊“撥打該號碼”後,系統自動進入撥號介面,所以也是典型的跨進程測試情境。

 

實現方法還是跟例1中一樣,先還是用uiautomatorviewer查看介面中的對象資訊,再使用對應的方法來操作對象即可。而且在這個例子中,我還給大家示範了另外一種情況,即有些跨進程操作不但要進行操作,還要取得一些對象屬性來進行驗證,這也是基本可以的。這裡我直接給出我的測試代碼(稍微封裝了一下):

public boolean CallUtil(String callNumber){        Element  element;        boolean  result;        //驗證是否撥打了正確的號碼        if(callNumber.length() == 11){//正常號碼需要轉變為 x xxx-xxx-xxxx的格式                StringformatCallNumber = callNumber.substring(0, 1) + " " +callNumber.substring(1, 4) + "-" + callNumber.substring(4,7) +"-" + callNumber.substring(7, callNumber.length());                element= position.findElementByText(formatCallNumber);                try{                        Thread.sleep(2000);  //線程休眠2秒                }catch (InterruptedException e) {                        e.printStackTrace();                }        }else{                element= position.findElementByText(callNumber);//除正常號碼外,其他格式的號碼不進行格式轉換        }        if(element != null){                result= true;        }else{                result= false;        }        element= position.findElementByContentdesc("End");   //掛斷電話        if(element != null) adbDevice.tap(element);        return  result;}

好了,整個過程非常簡單。我相信能用robotium的童鞋用起來應該都沒有任何問題,所有代碼都是非常易用易懂的。

 

相信通過前面的執行個體,大家可以發現說這是“史上最簡單”的Robotium跨進程操作解決方案我估計沒人會反對,這並不是誇大事實、博人眼球,確實很簡單,功能也很強大。其他也不用我多說了,最後我再來對該架構總結一下下吧:

優點:

1. 確實非常全,基本封裝了adb的所有常用命令,它本身就是一個adb命令使用大全了。

2. 架構介面設計清晰易懂,簡單明了,封裝成jar包,用起來也很方便。另外希望大家都能看看它的源碼並瞭解它的實現細節,作者封裝得還是很不錯的,很值得我們學習,而不僅僅是簡單地使用它。

3. 不需要root許可權。其實這點還是很重要的,有些公司的測試機是沒有root許可權,用adb就很方便。對於不想放棄robotium,又確實有跨進程操作需求的童鞋來說,真的是非常實用的一個架構。

 

目前已知的不足:

1. 手機的版本必須是4.1以上,即至少必須支援uiautomator的手機才行,因為該架構本身底層是依賴於uiautomator來dump出物件版面配置xml檔案,最終擷取對象的座標進行操作的,所以你的手機版本本身並不支援uiautomator的話,就沒法實現dump操作。

2. 有些對象是uiautomator也無法識別和操作的,那當然這個架構也無能為力了。比如螢幕最上方的通知訊息欄的對象,所有工具都沒法顯示和識別,這個肯定沒辦法了,另外還比如輸入文字時的彈出鍵盤上的按鈕對象等,也無法識別,大家可以試試。

 

以後想要嘗試的改進:

1. 對於手機版本的支援問題,個人覺得有個曲線救國的方法可以解決。即我們可以稍微修改下源碼,加入判斷手機版本的代碼,判斷當前手機版本如果高於4.1,就直接通過uiautomator來dump,如果低於4.1,則讀取PC上事先匯出到指定位置的xml檔案。這樣的話,如果你使用的手機不是4.1以上的版本,只需要事先把被測應用用4.1以上版本的手機通過uiautomator先dump到PC的一個指定路徑上就行了,這樣效果應該是一樣的,只要最終能得到對象座標就OK。

2. 再加一些比較實用的功能。比如現在可以根據text來尋找對象,但實際上很多時候我們可能是得到對象了,但想通過這個對象去擷取對象的其他屬性,所以建議增加類似getXXXXByElement(Element e)這樣的方法,有空試一下,呵呵。

 

以上只是我的一些個人想法,如果大家還有一些什麼別的建議,也歡迎大家都提出來,一起來完善這個很實用的架構。

 

最後,再次感謝AdbForAndroid架構的作者: xuxu。

架構源碼github地址:https://github.com/gb112211/Adb-For-Test

本文中相關範例工程源碼(含被測程式和測試程式)下載

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.