InstrumentDriver,對iOS自動化測試說 Yes!

追憶丶年華發表於2018-01-25

InstrumentDriver 是 Mobile自動化小組最近實現的基於 instrument,針對 iOS 的自動化測試框架,目前支援 java 語言編寫測試用例。 研究過iOS自動化測試的同學肯定對 instrument UI Automation 有所耳聞,或者已經使用它進行自動化測試實踐。iOS 4.0

  InstrumentDriver 是 Mobile自動化小組最近實現的基於 instrument,針對 iOS 的自動化測試框架,目前支援 java 語言編寫測試用例

  研究過iOS自動化測試的同學肯定對 instrument UI Automation 有所耳聞,或者已經使用它進行自動化測試實踐。iOS 4.0 開始,蘋果官方提供了 UI Automation 以支援應用的UI自動化測試。不過4.0版本並不支援錄製功能,只能根據提供的API文件編寫 javascript 測試指令碼,instrument 驅動指令碼在應用上模擬使用者行為。

  讓人興奮的是,5.0開始,UI Automation 支援錄製和回放了。使用者在應用上的操作過程被記錄下來並生成對應的指令碼可以進行回放。雖然錄製的指令碼回放很不穩定,健壯性不強,錄製後需要進行一些簡單調整然後加入自己的校驗邏輯,但已經很大程度上方便了用例的編寫。

  針對 instrument 錄製的指令碼回放不穩定,無提供驗證框架及異常處理,我們編寫了公共 javascript 類庫,對 instrument 原型進行了擴充套件,加入了統一的驗證方法,異常處理,這樣編寫指令碼更加方便,用例也更健壯了。

  自動化測試不是簡單的錄製回放,指令碼執行通過就可以了,而是一整套的流程。instrument 支援批量執行 trace 檔案中匯入的 js 指令碼,也支援命令列執行單個指令碼,但是這並不能建立一個比較完善的迴歸體系,從資料準備,到用例編寫、除錯、維護,迴歸,執行結果的收集,到測試報表的生成,結果的分析等。針對這些缺失,我們只能從中想出辦法補充實現這些功能。比如編寫shell遍歷目錄挨個執行用例,開發日誌轉換的工具用於解析原始測試結果生成所需格式的檔案等。由於 instrument 中 js 指令碼無法讀取外部檔案或者進行資料庫操作,這也讓資料驅動和資料準備無從談起。

  在內部使用 instrument UI Automation 進行自動化測試的過程中有很多反饋。比較強烈的問題是:錄製的指令碼如同雞肋,非常冗餘,可讀性差(指令碼自描述性不好),難以維護,需要進行較大改動才能執行起來;無法單步除錯指令碼,只能通過打日誌的方式檢視變數的值;js編寫指令碼也比較費力,經常出現語法錯誤找不到錯誤位置的情況。這大大增加了自動化測試的成本,減低了同學們的使用積極性。

  自動化測試是好東西,實施好了,能極大減輕測試人員的重複勞動,節省時間用於關注更深層次的問題,提高工作效率與質量,更好的保障產品的質量。

  雖然過程是曲折的,但前途是光明的。為了從根本上避免上述使用過程中遇到的問題,我們開始想辦法脫離 js 編寫指令碼的方式,通過編寫java測試用例,來避免指令碼無法單步除錯、檢視變數值,無自動語法檢查、程式碼智慧感知等極大影響自動化測試體驗的弊端。java強大的檔案讀寫,資料庫操作也讓資料驅動和資料準備的實現成為可能。加上java能與豐富的外部工具進行方便的整合,這更堅定了我們採用java實現的決心。

  由於iOS系統本身的封閉性,給自動化測試帶來了諸多挑戰,要麼在應用中注入測試程式碼進行自動化測試(eg:我們的 AppFramework),要麼使用官方的 instrument。兩種方式各有利弊,怎樣在這之中尋求一種更好的方式呢?通過調研發現 instrument 提供的一個在指令碼中能夠呼叫外部shell的“漏洞”,讓我們想法的實現成為可能。基於此,有了 InstrumentDriver 的實現。

  InstrumentDriver 整體框架圖:

圖1 InstrumentDriver 整體框架圖

  圖1 InstrumentDriver 整體框架圖

  Server/Client 示意圖:

圖2 Server/Client 通訊示意圖

  圖2 Server/Client 通訊示意圖

  InstrumentDriver 的實現有以下功能特點:

  1. C/S 模式執行。

  框架分為Server端和Client端,雙方進行socket通訊傳遞訊息:Client端(Mobile)負責請求測試步驟執行,並返回執行結果;Server端(Java用例)負責響應Client請求並接受測試步驟的執行結果。C/S模式的實現,甚至可以脫離Mac在PC上編寫、除錯測試用例(執行肯定離不開Mac系統),在熟悉的window環境下,讓用例編寫更加得心應手。

  2. 純Java語言編寫測試用例,很好的相容了instrument js格式的API。

  InstrumentDriver 用Java實現了各元素型別的之間的繼承關係以及各元素型別所提供的操作方法,還擴充套件了一些更易於使用的操作,如滑動操作等。熟悉instrument js語法格式的測試人員可以很快用java語言實現測試用例。

  3. 提供了清晰的控制元件樹狀結構列印及便利的元素查詢方法。

  可以樹狀結構列印出當前視窗的所有元素或某一元素下的所有子元素。輸出屬性中不僅包括各元素的基本屬性(name,value,label,rect等),更包括代表該元素的guid,用例中直接使用該guid屬性即可代表該元素進行相應操作。findElemenByText及相關過載方法可以很方便的根據元素的顯示文字,型別,索引組合查詢該元素,極大提升了用例的自描述性和可維護性,也更好的簡化了用例的編寫。

  4. Debug模式和非Debug模式執行

  用例可以debug模式和非debug模式兩種方式執行。debug模式通訊時傳遞json物件或陣列,返回後例項化為具體物件。可以除錯指令碼,檢視相關物件的屬性值。非debug模式僅在需要操作UI元素或獲取UI元素屬性的時候才通訊,較大的提升了執行速度(debug模式的2倍左右)。可以這麼認為:用例debug模式通過後,非debug模式也能執行通過。

  5. Junit方式執行測試用例

  InstrumentDriver 以大家熟悉的Junit方式驅動測試用例,具備了Junit單元測試的所有優點。可以更好結合其它工具進行持續整合和資料準備。如結合svn,maven,hudson進行持續整合,通過iTest進行資料準備等。

  一些截圖說明:

  下圖是UI Automation錄製的指令碼截圖

  可以看到,指令碼非常冗長,只能通過元素的子元素一級級往下查詢,很多索引方式生成的指令碼自描述性不高,頁面稍有變化,不能很快找到對應的指令碼進行更改,這樣維護成本是很高的。

圖3 UI Automation錄製的指令碼截圖 對比 InstrumentDriver 的 java用例,同樣功能的用例實現截圖如下: 圖4 InstrumentDriver java 用例 可以看出 InstrumentDriver 提供的 pr

 

圖3 UI Automation錄製的指令碼截圖

  圖3 UI Automation錄製的指令碼截圖

  對比 InstrumentDriver 的 java用例,同樣功能的用例實現截圖如下:

InstrumentDriver java 用例

  圖4 InstrumentDriver java 用例

  可以看出 InstrumentDriver 提供的 printElementTree 方法可以列印出當前window所有元素, findElementByText 方法能很精確的查詢到相應元素。這樣根據指令碼就知道這一步驟的具體行為,自描述性大大提升,可維護性更好。

  下圖是 printElementTree() 方法 的具體輸出,樹形列印出win下的所有元素:

PrintElementTree 輸出示例

  圖5 PrintElementTree 輸出示例

  這裡我們可以根據輸出方便的找到需要操作的元素,並且可以直接使用該元素的 guid 屬性代表該元素,插入用例進行相應的操作。更推薦的做法是使用findElementByText進行定位,假如text(name,value ,label屬性)都為空,可以檢視父級元素或者更上級元素是否有text屬性,然後使用elements() 索引定位,可以最大化縮小範圍,使指令碼更健壯,可讀性更高。

  下圖是用例除錯過程中,變數值的檢視示例:

圖6 debug 模式除錯用例,檢視變數值

  圖6 debug 模式除錯用例,檢視變數值

  Debug模式執行,Client 會詳細返回對應操作的資訊,Server 端接收後例項化為具體物件,除錯中可以檢視具體物件的屬性值(name ,value,label,rect,guid),方便除錯用例,更快的找到問題所在。

  InstrumentDriver 剛剛誕生,正逐漸用於iOS自動化測試中,肯定還有很多改進的地方。希望在使用過程中得到更多的反饋,通過不斷改進,進一步讓它完善起來,更好的服務於大家。

相關文章