綜述
本文主要介紹了多端自動(dòng)化的實(shí)踐經(jīng)歷而非作為airtest的科普文章(因?yàn)閍irtest的官方文檔真的是已經(jīng)特別全了,非常建議實(shí)踐之前先看一遍文檔缭嫡,大部分問(wèn)題都能達(dá)到答案)妇蛀,主要敘述了在面對(duì)多端大規(guī)模場(chǎng)景時(shí),自動(dòng)化的技術(shù)選型眷茁、方案設(shè)計(jì)上祈、實(shí)踐難點(diǎn)等等浙芙。
項(xiàng)目背景介紹
所在項(xiàng)目是一個(gè)多端互動(dòng)的場(chǎng)景,是一對(duì)多的業(yè)務(wù)實(shí)現(xiàn)纸俭,具體是由一臺(tái)winpad的教師端揍很,對(duì)多臺(tái)安卓的學(xué)生端,在同一局域網(wǎng)內(nèi)箭启,進(jìn)行指令的發(fā)送和接收蛉迹,從而產(chǎn)生互動(dòng)北救,指令的中轉(zhuǎn)由臺(tái)服務(wù)(服務(wù)器+AP)實(shí)現(xiàn)。
需求產(chǎn)生的背景介紹
原始的客戶訴求托启,是因?yàn)闃I(yè)務(wù)測(cè)試在執(zhí)行這樣一對(duì)多的測(cè)試(以下簡(jiǎn)稱(chēng)為大規(guī)娜林妫互動(dòng))中蹭劈,因?yàn)樾枰鎸?shí)模擬場(chǎng)景,所以往往需要在一臺(tái)教師端和60臺(tái)學(xué)生端之間來(lái)回操作多矮,極為消耗人力資源(平均一次大約需要2人1天的工時(shí))塔逃,因此希望得到一種技術(shù)手段料仗,節(jié)約在大規(guī)模互動(dòng)測(cè)試中的開(kāi)銷(xiāo)淹仑。
技術(shù)選型
基于原始的客戶訴求匀借,我們將具體實(shí)現(xiàn)定義為了ui自動(dòng)化類(lèi)型平窘,以下是技術(shù)選型的分析過(guò)程瑰艘。
技術(shù)要求
-
統(tǒng)一性
大規(guī)姆粑瑁互動(dòng)產(chǎn)生在不同的系統(tǒng)間均蜜,教師端的系統(tǒng)是win10囤耳,而學(xué)生端的系統(tǒng)是android,因此德玫,我們希望最好可以由同一套框架實(shí)現(xiàn)對(duì)兩端的驅(qū)動(dòng)宰僧,這樣整體便于設(shè)計(jì)和驅(qū)動(dòng)观挎。
-
高兼容性
由于教師端的實(shí)現(xiàn)并不是標(biāo)準(zhǔn)的windows應(yīng)用實(shí)現(xiàn)方法键兜,而是通過(guò)c+nodejs再由electron做封裝,因此,很多元素用傳統(tǒng)的windows的查找框架uiautomation不易找到现诀,而由于客戶端對(duì)webview的實(shí)現(xiàn)寫(xiě)死了啟動(dòng)參數(shù)履肃,因此也無(wú)法通過(guò)傳統(tǒng)的cdp進(jìn)行定位尺棋,因此,我們希望可以有一個(gè)相對(duì)兼容的解決辦法去定位元素成福。
-
低侵入性
在學(xué)生端荆残,有著rom級(jí)的mdm安全管控内斯,對(duì)安裝應(yīng)用像啼、網(wǎng)絡(luò)進(jìn)出忽冻、adb連接等待都有著嚴(yán)格的規(guī)則此疹,且mdm是和供應(yīng)商聯(lián)合制定的秀菱,如果要對(duì)某些地方放行,會(huì)面臨較大的實(shí)現(xiàn)成本問(wèn)題赶么,因此辫呻,我們希望整體的實(shí)現(xiàn)方案具有較低的侵入性琼锋。
方案對(duì)比
經(jīng)過(guò)調(diào)研缕坎,具備以上要求的方案大概有以下:
-
airtest
網(wǎng)易出品的主打圖像識(shí)別的開(kāi)源自動(dòng)化測(cè)試框架,具備三端(web匾寝、移動(dòng)艳悔、win)驅(qū)動(dòng)能力女仰;且相關(guān)ide疾忍、文檔、使用經(jīng)歷較為齊全袁稽。
-
騰訊QTA
騰訊出品的開(kāi)源自動(dòng)化測(cè)試框架推汽,具備三端驅(qū)動(dòng)能力,但截至調(diào)研期間莲组,其win端的驅(qū)動(dòng)包還未放出锹杈。
-
學(xué)生端appium+教師端pywinauto
appium是老牌的移動(dòng)端測(cè)試框架迈着,pywinauto是win端的gui測(cè)試框架裕菠,他們皆可由py進(jìn)行封裝驅(qū)動(dòng)。 但appium存在需要在移動(dòng)端安裝其服務(wù)apk以及通信的需求旧烧,會(huì)受到mdm管控掘剪。
-
學(xué)生端AccessibilityService+以上教師端方案
通過(guò)AccessibilityService可以實(shí)現(xiàn)學(xué)生端的元素控制奈虾,使得學(xué)生端可以無(wú)需連接控制設(shè)備肉微,直接在本機(jī)即可運(yùn)行,但后續(xù)擴(kuò)展能力較低,且難以與教師端實(shí)現(xiàn)相互通信村象。
綜合以上選擇厚者,認(rèn)為 airtest 現(xiàn)階段較為合適迫吐,并且由于是局域網(wǎng)內(nèi)的大規(guī)模通信場(chǎng)景志膀,對(duì)無(wú)線帶寬本身就有壓力鳖擒,因此蒋荚,對(duì)學(xué)生端的驅(qū)動(dòng)方式采用有線adb而非無(wú)線的方式期升。
方案設(shè)計(jì)
整體架構(gòu)
原本更為合適的架構(gòu)形態(tài)可能是通過(guò)rpc的方式完成端對(duì)端通信(具體參見(jiàn)文檔:基于rpc的多端互動(dòng)自動(dòng)化方案)互躬,由于時(shí)間和人力所限吼渡,最后簡(jiǎn)化為端對(duì)端之間互不通信诞吱,學(xué)生端通過(guò)元素輪詢完成教師端行為的響應(yīng),具體架構(gòu)如下:
1.環(huán)境需求:
硬件
- 學(xué)生端執(zhí)行服務(wù)器 *2臺(tái)沼瘫;
- 教師端執(zhí)行服務(wù)器 *1臺(tái)(如果也在學(xué)生端執(zhí)行服務(wù)器上那么可以沒(méi)有)咙俩;
- UsbHub *2臺(tái)阿趁;
- 學(xué)生pad *60臺(tái)脖阵;
軟件
- 學(xué)生端腳本;
- 教師端腳本
網(wǎng)絡(luò)
- 局域網(wǎng)環(huán)境(超腦環(huán)境)
2.執(zhí)行過(guò)程:
usbhub分別連接上各30臺(tái)學(xué)生端機(jī)器以及執(zhí)行學(xué)生端腳本的服務(wù)器呜呐;
-->
在學(xué)生端執(zhí)行服務(wù)器上啟動(dòng)學(xué)生端腳本蘑辑,此時(shí)學(xué)生端進(jìn)入元素輪詢狀態(tài)洋魂;
-->
在教師端執(zhí)行服務(wù)器上啟動(dòng)教師端腳本,通過(guò)教師端本身的反饋判斷學(xué)生端是否做完對(duì)應(yīng)動(dòng)作
-->
收集測(cè)試結(jié)果
腳本設(shè)計(jì)
腳本架構(gòu)
腳本的基本設(shè)計(jì)采用元素映射關(guān)系衔肢、配置文件址晕、執(zhí)行步驟互相分離的方式膀懈,各端的腳本放置在xxx.air的文件夾里,通過(guò)airtest本身的啟動(dòng)cli執(zhí)行谨垃。
腳本的目錄結(jié)構(gòu)大致如下:
|-- configs(存放項(xiàng)目運(yùn)行設(shè)置的配置文件目錄)
|'-- run.config
|-- logs(記錄運(yùn)行時(shí)log文件的目錄)
|-- templates(存放報(bào)告模板目錄)
|'-- report_tpl.html
|-- test_XXX.air(某個(gè)端的執(zhí)行腳本)
|'-- action.config(某個(gè)端的運(yùn)行配置)
|'-- element.config(某個(gè)端的元素映射文件)
|'-- test_xxx.py(某個(gè)端的執(zhí)行動(dòng)作腳本庫(kù))
|'-- utils.py(工具集方法)
|-- valid_pic(存放斷言用圖片的目錄)
|-- run.py(總運(yùn)行入口)
腳本實(shí)現(xiàn)能力
腳本主要實(shí)現(xiàn)了以下能力:
-
覆蓋了學(xué)生端启搂、教師端的互動(dòng)主要場(chǎng)景的動(dòng)作執(zhí)行;
-
覆蓋了互動(dòng)主要場(chǎng)景的耗時(shí)統(tǒng)計(jì)刘陶;
-
教師端胳赌、學(xué)生端分別由配置文件定制主要場(chǎng)景的執(zhí)行細(xì)節(jié)(例如執(zhí)行次數(shù),動(dòng)作參數(shù)等等)
-
集成了非主要場(chǎng)景但是常用的工具集(例如adb連接檢測(cè)匙隔,自動(dòng)安裝卸載apk等等)
-
疑苫。纷责。捍掺。
關(guān)鍵技術(shù)點(diǎn)實(shí)現(xiàn)
-
多進(jìn)程驅(qū)動(dòng)學(xué)生端執(zhí)行用例
由于互動(dòng)場(chǎng)景基于1對(duì)多,在學(xué)生端這邊需要多臺(tái)設(shè)備進(jìn)行場(chǎng)景互動(dòng)再膳,因此挺勿,需要同時(shí)驅(qū)動(dòng)多臺(tái)設(shè)備,在實(shí)現(xiàn)上喂柒,我們查閱了官方資料不瓶,采用了其建議的方式,通過(guò)起多個(gè)進(jìn)程灾杰,每個(gè)進(jìn)程分別帶參執(zhí)行airtest的cli命令蚊丐,從而達(dá)到多設(shè)備驅(qū)動(dòng)的目的。
-
圖像識(shí)別下的斷言
如前文艳吠,在精簡(jiǎn)的框架設(shè)計(jì)下麦备,多端互動(dòng)是通過(guò)學(xué)生端輪詢?cè)貋?lái)執(zhí)行互動(dòng)流程的,但是仍然需要對(duì)互動(dòng)結(jié)果的正確性進(jìn)行校驗(yàn)昭娩。這里由于框架的限制泥兰,我們只采取了單端校驗(yàn),即只對(duì)教師端的互動(dòng)數(shù)據(jù)進(jìn)行校驗(yàn)题禀,比如如果有30個(gè)學(xué)生作答成功,那么我們就對(duì)教師端的結(jié)果頁(yè)面進(jìn)行校驗(yàn)膀捷,看答題人數(shù)是否是30迈嘹。
具體到校驗(yàn)手段,由于windows端較難獲取元素屬性,所以我們采用了對(duì)關(guān)鍵點(diǎn)進(jìn)行ocr識(shí)別的方式秀仲,具體請(qǐng)見(jiàn)文檔 在airtest中使用ocr反向識(shí)別進(jìn)行斷言融痛。
-
執(zhí)行過(guò)程內(nèi)性能數(shù)據(jù)的收集
數(shù)據(jù)收集是指在執(zhí)行過(guò)后,需要給出場(chǎng)景的耗時(shí)神僵,例如指令的接受耗時(shí)雁刷、頁(yè)面的加載耗時(shí)等等,這塊主要是通過(guò)在學(xué)生端設(shè)備上記錄一個(gè)時(shí)間保礼,作為開(kāi)始時(shí)間沛励,然后測(cè)試結(jié)束后,提取該設(shè)備上的日志分析炮障,最后得出耗時(shí)數(shù)據(jù)目派。
-
易混淆元素的記錄
由于采用的是圖像識(shí)別的模式,難免遇到元素圖像相似的情況胁赢,針對(duì)這種情況企蹭,采用的方法是擴(kuò)大可識(shí)別范圍截取元素,并使用target_pos參數(shù)更改選取區(qū)域智末。
應(yīng)用過(guò)程問(wèn)題與解決
本部分以問(wèn)答的形式展現(xiàn)在airtest應(yīng)用過(guò)程里存在的一些問(wèn)題和解決辦法谅摄。
-
為什么執(zhí)行windows端腳本的時(shí)候,鼠標(biāo)可以移動(dòng)到元素上但是執(zhí)行動(dòng)作失斚倒荨送漠?
在win端,airtest的底層是pywinauto它呀,并且基本沒(méi)有任何二次開(kāi)發(fā)螺男;遇到這個(gè)問(wèn)題,如果排除掉本身腳本的邏輯纵穿、語(yǔ)法問(wèn)題下隧,那么可以試試以管理員身份運(yùn)行腳本。
-
我必須要用官方的ide嘛谓媒?
airtest雖然附帶了一個(gè)官方的ide淆院,但是非常不建議把它用作項(xiàng)目的ide,作為項(xiàng)目級(jí)的ide還是比較欠缺工程目錄管理能力和基本的代碼檢查能力等句惯;
建議的方法是土辩,ide僅用作抓取元素時(shí)的錄制工具,但是項(xiàng)目級(jí)別的管理最好還是使用知名的ide抢野。
-
為什么有些windows的窗口用title連接不上拷淘?
如果不是你的語(yǔ)法有問(wèn)題,并且你“看起來(lái)”title寫(xiě)的也對(duì)指孤,那么可以在識(shí)別的時(shí)候在pywinauto的底層代碼里启涯,打個(gè)斷點(diǎn)贬堵,把所有窗口名稱(chēng)用bytes類(lèi)型打印出來(lái)看一下;
pywinauto的連接過(guò)程里结洼,是先遍歷所有窗口黎做,然后按你的連接類(lèi)型做匹配,這里打個(gè)斷點(diǎn)松忍,可以看一下你寫(xiě)的title是不是真的對(duì)蒸殿,因?yàn)樵趯?shí)際的項(xiàng)目里,我們遇到了看起來(lái)是對(duì)的title名稱(chēng)鸣峭,但是無(wú)論如何匹配不上宏所,導(dǎo)致無(wú)法連接,最后用bytes模式打印出來(lái)看叽掘,發(fā)現(xiàn)是因?yàn)檫@個(gè)窗口的title前面有三個(gè)不可見(jiàn)字符(直接print你是看不見(jiàn)的)楣铁。
-
如何提高元素的查找速度?
和傳統(tǒng)的通過(guò)元素屬性查找的方式不同更扁,airtest是基于圖像識(shí)別的盖腕,因此,在提高元素查找效率方面浓镜,方法也和傳統(tǒng)的有些不同溃列;一個(gè)基本的原則是,被查找的元素的截圖膛薛,在整個(gè)畫(huà)面里越獨(dú)一無(wú)二听隐,越具備特征性(圖形的特征性而不是顏色),那么就越容易被找到哄啄;此外雅任,在對(duì)元素的映射關(guān)系記錄里,增加record_pos和resolution的值咨跌,會(huì)極大的增加查找速度和效率沪么。
-
怎么對(duì)沒(méi)找到元素的情況進(jìn)行調(diào)試?
和傳統(tǒng)的通過(guò)元素屬性的查找方式不同锌半,基于圖像識(shí)別的查找方式不存在找不到元素禽车,對(duì)圖像識(shí)別而言,它總是能找到元素的刊殉,區(qū)別只是查找到元素的匹配度(threshold)而已殉摔,airtest默認(rèn)的threshold是0.7,也就是說(shuō)记焊,在他認(rèn)為元素的匹配度為70%以上時(shí)逸月,就認(rèn)為找到了這個(gè)元素,才會(huì)對(duì)這個(gè)元素進(jìn)行操作遍膜。
不幸的是彻采,往往達(dá)到0.7腐缤,也不一定就是真的找到了(但達(dá)不到一般是真沒(méi)找到),如果達(dá)不到匹配度肛响,或者達(dá)到了但也不對(duì),可以在airtest的框架里打斷點(diǎn)惜索。
airrtest的查找機(jī)制是先把當(dāng)前待查找的界面進(jìn)行截圖特笋,我們稱(chēng)為圖1;然后再根據(jù)你的record_pos巾兆,在圖1里算出待識(shí)別區(qū)域猎物,然后把這個(gè)區(qū)域摳出來(lái)保存,我們稱(chēng)為圖2角塑;最后蔫磨,再把你的預(yù)先截圖的元素,在圖2里進(jìn)行查找圃伶,算出匹配度堤如,如果匹配度在要求之上,那么就記錄這個(gè)位置的坐標(biāo)用于操作窒朋。
因此搀罢,我們可以分別對(duì)圖1,圖2設(shè)定指定的保存目錄侥猩,執(zhí)行一遍后看一下榔至,到底是對(duì)比對(duì)象出了問(wèn)題,還是真的我們?cè)亟貓D特征還不夠欺劳。