一、背景
一年前,我們一直在用monkey進行Android 的穩定性測試 ,主要目的就是為了測試app 是否會產生Crash,是否會有ANR,頁面錯誤等問題,在monkey測試過程中,實現了脫離Case的依賴,但是monkey測試完全隨機、不可控,並且只支持Android系統,不支持iOS系統;然而在我們不斷的實踐中發現,monkey測試已經不能滿足於我們的部分業務需求,比如說我們想讓穩定性測試更靈活、跨端支持iOS、日志可讀、定向場景設計、測指定頁面的穩定性、報告清晰展示遍歷結果等等,monkey在這些方面的實現局限性很大,經過我們調研發現開源工具appcrawler已然支持這些方面,在我們最近幾個版本的appcrawler使用過程中,能夠滿足我們復雜的業務測試需求,彌補了monkey測試的不足,下面我詳細的介紹這個自動化UI遍歷工具-appcrawler。
二、appcrawler UI自動化遍歷工具介紹
appcrawler,使用Scala編程語言運行在JVM上,它是基於app爬蟲的思想,逐漸形成了一種自動化測試方法稱為“UI遍歷”,其主導思想是盡可能多的去操作被測app的界面元素,每個元素至少操作一遍。支持android和iOS,支持真機和模擬器,最大的特點是靈活性,可通過配置來設定遍歷的規則,用於自動化回歸測試,實現對整個APP的所有可點擊元素進行遍歷點擊。
自動遍歷的價值
- 回歸測試,遍歷基本的界面,了解主要界面的可用性,比如兼容性,基本功能;
- 利用遍歷獲取app的加載時間和性能數據,需要借助其他的性能數據抓取工具,比如OneApm,NewRelic;
- 利用遍歷驗證app的內存泄漏以及穩定性等功能,需要借助LeakCanary和MLeaksFinder;
- UI diff 驗證新老版本的功能差異,並識別細節的問題;
- 抓取接口請求 輔助驗證一些模塊基本接口,並輔助分析接口調用流程,為接口測試做准備;
三、為什么用這個工具
- 支持android和iOS,支持真機和模擬器;
- 可通過配置來設定遍歷的規則(比如設置黑名單和白名單,提高遍歷的覆蓋率);
- 其本身的遍歷深度覆蓋較全,比如它擁有APP的dom樹,根據每個activity下的可點擊元素逐個點擊,比monkey更具有規律性,覆蓋更全面;
- 生成的報告附帶截圖,可以精確看到點擊了哪個元素及結果,對crash類的問題定位清晰;
- 各大雲市場上自動遍歷功能都多有限制企業無法自由定制.;
- 解決monkey等工具可控性差的缺點;
- 發現深層次的UI兼容性問題;
- 通過新老版本的diff可以發現每個版本的UI變動范圍;
四、設計理念
appcrawler UI遍歷基於app爬蟲思想,為了更好的認識app爬蟲,這里先介紹一下網絡爬蟲,在了解網絡爬蟲框架之后,您將會對app爬蟲有一個清晰的認知。
網絡爬蟲
通用網絡爬蟲又稱全網爬蟲(Scalable Web Crawler),爬行對象從一些種子 URL 擴充到整個 Web,主要為門戶站點搜索引擎和大型 Web 服務提供商采集數據。這里主要對爬蟲以及抓取系統進行一個簡單的概述。
一、網絡爬蟲的基本結構及工作流程
一個通用的網絡爬蟲的框架如圖所示:
網絡爬蟲的基本工作流程如下:
1.首先選取一部分精心挑選的URL放入種子URL隊列中;
2.將種子URL隊列中URL放入待抓取URL隊列;
3.從待抓取URL隊列中取出待抓取的URL,解析DNS,並且得到主機的ip,並將URL對應的網頁下載下來,存儲進已下載網頁庫中。此外,將這些URL放進已抓取URL隊列。
4.分析已抓取URL隊列中的URL,分析其中的其他URL,並且將URL放入待抓取URL隊列,從而進入下一個循環。
抓取策略:
在爬蟲系統中,待抓取URL隊列是很重要的一部分。待抓取URL隊列中的URL以什么樣的順序排列也是一個很重要的問題,因為這涉及到先抓取那個頁面,后抓取哪個頁面。而決定這些URL排列順序的方法,叫做抓取策略。下面介紹兩種常見的抓取策略:
1.深度優先遍歷策略
深度優先遍歷策略是指網絡爬蟲會從起始頁開始,一個鏈接一個鏈接跟蹤下去,處理完這條線路之后再轉入下一個起始頁,繼續跟蹤鏈接。我們以下面的圖為例:
遍歷的路徑:A-F-G E-H-I B C D
2.廣度優先遍歷策略
廣度優先遍歷策略的基本思路是,將新下載網頁中發現的鏈接直接插入待抓取URL隊列的末尾。也就是指網絡爬蟲會先抓取起始網頁中鏈接的所有網頁,然后再選擇其中的一個鏈接網頁,繼續抓取在此網頁中鏈接的所有網頁。還是以上面的圖為例:
遍歷路徑:A-B-C-D-E-F G H I
app爬蟲
app爬蟲比web端更容易抓取,大部分也都是http/https協議,返回的數據類型大多數為json。也就是指app爬蟲會先抓取啟動app后初始頁面的所有URL,然后再選擇其中一個URL進行抓取,然后讀取URL、解析URL、執行URL,下面對app爬蟲做詳細的概述。
一個app爬蟲的基本結構及工作流程、通用的app爬蟲的框架如圖所示:
為了更好的理解app爬蟲思想,下面app爬蟲的工作流程中,括號中內容時結合業務做的解述。
app爬蟲的基本工作流程如下:
1.進入app,首先獲取當前BaseURL,支持類型:http、https、ftp、file(比如啟動百度外賣app后有N個url);
2.將這些URL放入待抓取的隊列(待抓取即待遍歷,也就是說有些元素點擊后會生成新的url);
3. 從待抓取的隊列中取出即將抓取(待遍歷)的URL,讀取URL,並解析attribute、Label、name放入堆棧中;
4.遍歷(執行)已抓取URL中的所有元素,分析當前URL隊列是否包含baseURL,如果包含則清空堆棧記錄重新計數(分析其中的其他URL,並將URL放入待抓取(待遍歷)的URL隊列中,從而進入下一個循環),如果不包含,則使用當前頁面,不再記錄堆棧;
抓取策略:
appcrawler中的采取的抓取策略是:深度優先策略(其中遍歷深度可配置)
五、appcrawler技術要點解析
5.1 appcrawler和appium 的關系
5.1.1 appium支持
appcrawler在selenium2.0支持的基礎上做了一個針對appium的封裝,類名叫MiniAppium,他具有如下的特色。
- 設計極簡,除了selenium的自身支持外,增加了幾個API用於app的測試;
- 封裝了appium命令的啟動停止
- 強大的斷言
5.1.2 AppiumClient.Scala負責與appium交互
1.監聽appium進程的信息(執行成功,執行失敗,停止等),從appium獲得包名和activity
2.通過xpath找到組件,對重名的id只使用第一個。每隔5秒找一次,找10次后如果還找不到,則放棄
3.對組件的操作(如:滑動,點擊,長按等)進行定義,動作是隨機取的(類似monkey,方法名也叫monkey),位置信息用的是通過xpath找到的x,y坐標
4. 對每次操作之后的界面截屏(如果界面改變的話)
5.獲取頁面結構(最多3次)解析xpath的時候拿到一個節點樹,對樹中所有節點遍歷,具體實現在TreeNode.scala和Tree
5.1.3 appium關鍵字
在selenium支持的基礎上只增加了少數幾個方法.:
see:元素定位與屬性提取
tap:點擊
send:入文本
swipe:滑動
原來scalatest的selenium的支持仍然全部可用. 比如click on id("login")
具體用法如下:
1. see()
唯一的元素定位API,see是引用了<阿凡達>電影里面一句台詞"I See You",它的作用是當你看到一個控件, 你應該可以根據看見的東西就可以定位它,並獲取到這個控件的屬性, 無須借助其他工具或者使用findElementByXXX之類的函數,比如有個Button, 名字是"登錄",它的id是account,定位它可以通過如下多種方式的任何一種:
• see("登錄")
• see("登")
• see("錄")
• see("account")
• see("acc")
• see("//UIAButton[@id="account"]")
• see("screen_name")("text")
• see("screen_name").nodes.head("text")
• see("action_bar_title")("text") 文本
• see("action_bar_title")("tag") 類型
• see("action_bar_title")("selected") 是否選中
如果當前界面中存在了有歧義的空間,比如其他一個名字為"登錄"的輸入框, 那么上述定位方法中定位中兩個控件的定位方法會失敗, 你需要自己調整即可,這就是關於元素定位你只需要用see這個方法即可。
2. 動作 tap send swipe
目前只封裝了3個動作. tap 、send 、swipe.
see("輸入手機號").send("13067754297")
see("password").send("xueqiu4297")
see("button_next").tap()
支持鏈式調用. 當然不推薦日常使用
//對三次連續出現的tip控件點擊三次.
see("tip").tap().tap().tap()
see("輸入手機號").send("13067754297").see("password").send("x297")
3. 斷言
支持標准的scalatest的should風格的斷言,支持兩種風格的斷言
assert風格
assert(2>1)
5.2 測試執行
1.定義URL
- 界面唯一性:每個screen都有一個唯一的id,這樣如果在報錯的截圖中就可以很容易找到那個url,如下圖所示
- android的url默認為當前的activity名字
- iOS沒有activity概念,默認使用當前頁面dom的md5值的后五位作為標記,如果頁面不變,那么這個md5值也不會變
- 也可以自己指定某些特征作為url,比如title或者某些關鍵控件的文本
- 控件的唯一性取決於這個url和控件自身的id name tag text loc等屬性
- 比如一個輸入框id=input,在多個頁面中都出現了
- 如果url為空,那么它只會被點擊一次
- 如果url設置為當前activiy的名字,那么有多少頁面包含它他就會被點擊多少次
- url的定義是一門藝術,可以決定如何優雅的遍歷
2.遍歷控制
遍歷控制依賴於項目目錄下的配置文件Baiduwaimai.yml, 里面有詳細的注釋解釋每個配置項的作用
3.如何寫配置文件Baiduwaimai.yml(運行的核心所在)
配置文件基本都是以key-value格式,所以可以用文本編輯器,然后改名為 .yml或者.json文件即可。這里展示一下百度外賣app的配置文件 Baiduwaimai.yml部分內容:
-
后退標記back
android默認是back鍵,不需要設定.
iOS上沒有back鍵,需要自己指定,通過xpath定位方式指定遍歷完所有控件應該點擊什么控件返回
-
黑名單black
控件黑名單為black方法,他會繞過id name或者text中包含特定關鍵詞的控件
url黑名單可以繞過特定的activity
-
遍歷的行為控制
整體的配置項應用順序為:
capability
androidCapability和iosCapability分別用來存放不同的平台的設置,最后會和capability合並為一個
startupActions
用於啟動時候自定義一些划屏或者刷新的動作
selectedList
- 適用於在一些列表頁或者tab頁中精確的控制點擊順序
- selectedList表示要遍歷的元素特征
- firstList表示優先遍歷元素特征
- lastList表示最后應該遍歷的元素特征
- tagLimit定義特定類型的控件遍歷的最大次數. 比如列表項只需要遍歷少數
- 需要注意的是firstList和lastList指定的元素必須包含在selectedList中
元素定位的方法
appcrawler大量的使用XPath來表示元素的范圍,大部分的選項都可以通過XPath來指定范圍,比如黑白名單,遍歷順序等
4. 點擊前后截圖
URIElementStore.scala負責記錄控件是否被點擊
1.使用枚舉類型,Clicked表示已遍歷,Skiped = Value表示跳過
2.使用elementStore(Map類型)存儲被點擊的組件列表。URIElement.scala用來代表唯一的控件,每個特定的命名控件只被點擊一次, 所以這個element的構造決定了控件是否可被點擊多次,如果組件url=baiduwaimai,key只有1個,所以只能點一次。如果組件url=baiduwaimai/xxxActivity,由於可能是不同Activity中的,所以可以點擊多次
截圖加紅框是如何實現的?
appcrawler使用了java的ImageIO庫, 可以對已有的圖片進行標記, appcrawler在點擊前會先識別元素的位置,並加上一個紅框用於提示.。
5.3 跨平台
Android UI遍歷
1.啟動appium
appium --session-override
2.啟動appcrawler UI遍歷
java -jar appcrawler-2.1.1.jar -a bdwm.apk -o demo/ --capability appActivity=.view.WelcomeActivityAlias
3.配置文件的運行方式
java -jar appcrawler-2.1.1.jar -a bdwm.apk -c conf/baiduwaimai.yml
4.跳過重新安裝app
java -jar appcrawler-2.1.1.jar -a bdwm.apk -c conf/baiduwaimai.yml --capability appPackage=waimai_4.11.6.apk
IOS UI遍歷
模擬器運行:
1.啟動appium
appium --session-override
2.啟動appcrawler 開始UI遍歷
java -jar appcrawler-2.1.1.jar -a bdwm.app -c conf/baiduwaimai.yml
xcode編譯出來的app地址可通過編譯過程自己查看
真機運行
使用xcode編譯源代碼, 使用開發證書才能做自動化,編譯出真機可自動化的.app或者.ipa包
java -jar appcrawler-2.1.1.jar -a bdwm.ipa -c conf/baiduwaimai.yml
5.4 自定義
5.4.1 Xpath的充分利用
獲取控件XPath路徑的工具
uiautomatorviewer(最常用)、名字、平台
Android:只能直接生成xpath, 需要自己拼湊
iOS:inspector,只能工作在mac上,
Android和iOS控件差異
tag名字是不一樣的.、控件布局不一樣
android.view.View
android.widget.XXXXX
關鍵的定位屬性也不一樣
iOS:name、label、value
Android:resource-id、content-desc、text
常見xpath表達式用法
5.4.2 插件化
1.代理插件
自動獲取app上每次點擊對應的網絡請求,支持http和https
- 安裝
目前是默認自帶
- 啟用
在配置文件中加入插件
代理插件默認開啟7771端口,配置你的Android或者iOS的設備的代理,指向你當前運行appcrawler的機器和7771端口
- 結果
在做每個點擊的時候都會保存這期間發送的請求, 也就是記錄前后兩次點擊中間的所有通過代理的請求,最后會在結果目錄里面生成后綴名為har的文件
- https支持
如果要錄制https,需要安裝一個特殊的證書"BrowserMob Proxy",或者用burp把當前端口設置為burp的上游代理,對於一些用url中包含有ip的https請求不支持
2. Log插件
- 作用
自動記錄Android的LogCat或者iOS的syslog
- 安裝
目前是默認自帶
- 啟用
在配置文件中加入插件
"pluginList" : [
"com.testerhome.appcrawler.plugin.LogPlugin"
],
- 結果
記錄一次點擊事件后所發生的log記錄, 並保存為后綴名為.log的文件中
3. TagLimit插件
- 作用
智能判斷列表和其他的相似布局元素,只遍歷前3個相似空間. 適用於微博這種無限刷新的列表, 用於節省時間,原理是利用特定元素的tag布局層級是否完全一樣
- 安裝
目前是默認自帶.
- 啟用
在配置文件中加入插件
"pluginList" : [
"com.testerhome.appcrawler.plugin.TagLimitPlugin"
],
- 結果
無
六、appcrawler使用流程
6.1 環境搭建
1. appcrawler的最新jar包(最新的功能多,兼容性比較高),目前最新的是 appcrawler-2.1.2.jar ,
2. appium環境安裝
3.Android SDK,主要是為了使用tools文件夾下的 uiautomatorviewer.bat 來定位元素,獲取元素的xpath,
6.2 appcrawler目錄結構
6.3 執行步驟
1. 手機安裝好最新的安裝包,
2.開啟appium服務
在命令行中輸入: appium ,提示: 則開啟成功
3.在放 appcrawler-2.1.0.jar 的文件夾下執行以下命令:
Java -jar appcrawler-2.1.0.jar -a bdwm.apk -c baiduwaimai.yml
或者如上目錄,運行start.py 腳本
即可自動啟動APP,並自動遍歷點擊元素
因為遍歷的深度比較大,在覆蓋比較全面的條件下,基本要跑2個半小時左右,截圖2600+張
4.輸出結果-日志和報告如下:
5. html報告:
七、目前的使用方向和收益
在每個版本的集成測試階段,會跑3次appcrawler UI 自動遍歷,整體測試方式是手工測試+自動遍歷
現在我們只在android端進行UI自動遍歷測試,運行2小時半左右,大約一小時截圖1000張,通過截圖+報告可以直觀的看到哪些頁面正常,哪些頁面異常
利用appcrawler發現bug2個:商超方向的一些空白頁面
八、工具問題分析
雖然appcrawler對我們app的穩定性測試帶了很客觀的收益,但是這個工具本身還是有一些不足需要改善,主要不足如下:
1. 測試速度可能比較慢,會對重復的界面進行點擊
2. 每個版本的配置文件或許有不同,對比三次測試,一方面是在相似的組件中可能漏掉比較重要的組件,另一方面是為了追求測試覆蓋,重復點擊了相似的界面組件。兩者不能很好地平衡
3. 配置文件有一定的局限性,有時不能很好地表達測試者的意圖
4. 不能自動輸入文本信息
九、后續TODO
后續我們會更加充分利用appcrawler,並進行二次開發,主要實現以下功能:
ios UI遍歷
多端執行,多個設備同時運行
和Jenkins結合
mail通知
調研第三方雲測平台