修改android monkey源碼使其支持UI自動化測試


在Android平台上,如果要實施自動化測試的話,有幾個方式,比如使用基於Instrumentation類庫及其衍生類,或者是使用monkeyrunner,測試用例運行在PC上,通過USB或者WIFI向Android手機的應用發送測試命令。這兩個方案各有優缺點:

1、 Instrumentation技術的優點是編寫UI自動化測試用例的技術跟編寫Android應用的技術是同一個技術,而且API也是使用Android本身的類庫。但是它的缺點是需要待測應用使用調試用密鑰進行數字簽名,這是因為Android平台強制要求一個應用如果要讀取或者修改另外一個應用的狀態的話,必須是同一個實體,而同一個實體的證據就是使用同一個密鑰進行數字簽名。因此使用Instrumentation技術來測試第三方應用的話,就必須先將第三方應用的數字簽名去掉,重新使用調試版密鑰簽名才能執行測試。如果應用里有資源文件需要使用原先的數字簽名才能解密的話,那么啟動重新簽名過的應用時,就會出現問題。例如QQ的Android版就是這種情況,重新簽名后,再啟動就會崩潰 – 從預防他人惡意復用知識產權的角度來說,是一個非常好的做法,但對於自動化測試就是另一種情況了。

2、 Monkeyrunner的缺點是,只能運行在PC機上,其運作原理是測試用例是在PC機上解釋用例腳本,通過網絡向Android手機的應用發送消息實現的。如果要求只能在手機上,完全脫離PC機的話,就沒辦法測試。例如要在實際測試運營商的網速和通信質量,測試人員可以拿市面上幾個流行的應用,寫幾個自動化測試用例,然后手持手機設備執行測試。

曾經碰到類似的測試需求,即要求只能在手機上運行,為類似QQ這樣不能重新簽名的Android應用編寫自動化測試用例……能夠滿足這個要求的測試技術只有monkey,可是不知道Google是出於什么考慮,只把monkey設計成一個隨機發送按鍵消息的程序 – 跟猴子一樣,在手機鍵盤上亂敲亂點;而沒有給monkey加上類似Instrumentation的抓取控件的支持。

為了滿足測試需求,我們對方案是修改了一點monkey的源代碼,實現在手機真機上,脫離PC機,無需重新簽名測試QQ的用例。修改的原理是:

1、 Android SDK里有一個工具HierarchyViewer可以顯示Android手機上各應用的UI布局,我們也實現了支持iOS的HierarchyViewer,有興趣的網友可以參閱:http://www.cnblogs.com/vowei/archive/2012/08/13/2614468.html

2、 HierarchyViewer的原理是通過與運行Android手機上的ViewServer建立一個socket連接(這個連接可以通過WIFI,也可以通過USB端口),向ViewServer發送命令的形式通信。

a) 例如,當HierarchyViewer發送 DUMP -1 這個指令時,ViewServer 就會將整個Android系統的UI樹形布局回傳給HierarchyViewer。

b) HierarchyViewer再解析回傳的字符串,關於這個過程,我的同事劉斌華寫了一篇非常好的文章:http://www.cnblogs.com/vowei/archive/2012/08/08/2627614.html

3、 因為HierarchyViewer是運行在PC機上的,而ViewServer是運行在手機上的,實際的抓取Android UI控件樹的過程是由ViewServer來完成的,HierarchyViewer只是一個簡單的客戶端。

4、 而Android系統又是多任務的,可以由好幾個程序同時運行在后台,在手機上抓取UI控件樹的過程就變得很簡單:

a) 建立到本機ViewServer的socket連接。

b) 跟HierarchyViewer一樣,向ViewServer發送命令並解析回傳的字符串,這個字符串可以用我們的iQuery解析:https://github.com/vowei/iQuery

c) 默認情況下,ViewServer是出於關閉狀態,需要顯式啟動。

下面是關鍵代碼,打開monkey主函數的源文件,Monkey.java,在其main函數里:

1、 在Monkey調用getSystemInterfaces之后,加上下面這行顯式啟動ViewServer – 其監聽的端口號是4939。

   1:  monkey.mWm.startViewServer(4939);

2、 然后在monkey源碼里,任意的合適的位置,創建一個socket,連接到本機的ViewServer上:

   1:  Socket socket = new Socket();
   2:  socket.connect(new InetSocketAddress("127.0.0.1", 4939));

3、 與ViewServer通信:

   1:  BufferedWriter out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
   2:  BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream(), "utf-8"));
   3:  out.write("DUMP -1");
   4:  out.newLine();
   5:  out.flush();
   6:  String line = null;
   7:  int maxCount = 0;
   8:  while ( (maxCount < 4) && ((line = in.readLine()) != null) ) {
   9:  ... ...
  10:  }

因為在手機上啟動ViewServer是一個超級用戶才能做的操作-需要打開一個網絡端口,需要使用一台root過的設備,運行方式是:

1、 找到一個root過的設備,並安裝一個Terminator應用。

2、在手機上啟動“終端模擬器”程序,並依次執行下列命令:

   1:  export CLASSPATH=/sdcard/monkey.jar
   2:  cd /sdcard
   3:  su
   4:  #下面這個命令默認會啟動QQ,並打印QQ登錄界面上4個TextView控件上的文本
   5:  app_process /system/bin com.android.commands.monkey.Monkey
   6:  #下面這個命令運行指定的Android應用 ,並打印界面上前4個TextView控件上的文本,第一個參數是包名,第二個參數是要啟動的Activity全名
   7:  app_process /system/bin com.android.commands.monkey.Monkey com.android.development com.android.development.Development


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM