前言
今天想先給大家分享1個小白用戶的Airtest從入門到放棄的故事:
小A是一個自動化的小白,在逛測試論壇的時候,偶然間發現了Airtest這個基於圖像識別的UI自動化框架。
出於好奇,小A試用了這個框架,發現只需要幾條簡單的截圖腳本,就可以對設備進行各種自動化操作,於是小A成功種草了這個框架。
但幾天之后,隨着小A的深入使用,他發現截圖腳本並不是他想象中那么“完美”。有時候程序會告訴他 找不到對應的截圖 ,有時候程序又會 識別到一些錯誤的位置 ,又或者他辛苦寫好的截圖腳本,換了一台手機之后,又都識別不到了......
在經歷了第N次失敗之后,小A最終還是放棄了這個框架。
看到這里,或許一部分同學會覺得感同身受,因為自己剛開始用Airtest這個框架的時候,也是經常踩到上面所說的坑!
Airtest作為1個自研的測試框架,它確實不能做到“完美”識別。但是除了期待以后我們的開發小姐姐小哥哥們研究出更精確的圖像識別方案之外,我們還有很多技巧可以提高我們截圖腳本的兼容性。
下文我們將先了解一下Airtest圖像識別原理相關的知識,然后在實際案例中,帶大家一起看看11個截圖技巧,幫助大家提升截圖腳本的兼容性。
關於Airtest截圖,你必須知道的幾個知識點
1. Airtest使用的圖像識別算法
默認情況下,Airtest會嘗試用 SURFMatching
、TemplateMatching
和 BRISKMatching
這三種算法來進行圖像識別。
其中 TemplateMatching
屬於 模板匹配算法,而 SURFMatching
和 BRISKMatching
則屬於 特征點匹配方法。簡單點說,模板匹配算法依賴 特征向量 來進行圖像匹配,而特征點匹配算法則是依賴於 圖像的特征點 。
這些算法對於設備畫面上唯一的圖標、圖像,識別效果會比較好,因為它們擁有比較多的特征向量/特征點,而對於像純文字截圖、含有大量空白背景的截圖,識別效果則會差一些。
我們都知道,純文字截圖中僅僅包含了一些簡單的筆划,特征向量/特征點會比較少,相對於圖像來說,更容易識別到錯誤的結果。而空白背景的截圖,各個像素點的灰度值基本沒有什么變化,所以特征點幾乎沒有,就更容易找不到匹配結果/匹配到天差地別的結果出來。
2. 程序如何根據算法結果判定是否找到匹配的截圖
那當我們編寫好截圖腳本,並開始運行的時候,程序是如何用這些圖像識別算法來幫助我們判定是否識別到結果的呢?
這里先介紹兩個很重要的名詞:闕值 和 可信度 ,他們的取值范圍都是[0,1]。在每一條圖像識別的腳本中,都會有1個用於結果篩選的闕值,默認值為0.7。
當上述三種算法在執行過程中識別到初始結果時,就會計算出來這個初始結果的可信度,當 可信度>闕值 的時候,程序會認為 找到了最佳的匹配結果 ;而當 可信度<闕值 的時候,程序則會認為 沒有找到最佳的匹配結果 。
我們可以在執行截圖腳本的時候,查看log窗口,觀察算法識別結果的可信度:
① 可信度>闕值,程序判定找到匹配結果
② 可信度<闕值,程序判定未找到匹配結果,循環用三種算法繼續查找直到超時
11條截圖技巧讓你輕松玩遍截圖自動化
了解完截圖相關的基礎知識之后,終於到了我們截圖技巧這部分的內容,不過需要注意的是,不同場景所應用的技巧的大不相同,希望同學們可以靈活使用:
1.截取圖標時盡量不要截入過多的背景內容
舉個簡單的例子,比如我們想通過點擊網易雲音樂的應用圖標來打開網易雲音樂的app,為了能在不同設備上都有更好的識別結果,我們應該盡可能選取下圖中第一種截圖,而不是混入了過多背景的第二種截圖:
為了讓大家直觀地看到差別,我們在設備1上截好了上述倆張圖,然后分別在設備2中執行,結果如下:
可以看到,沒有截入過多背景的截圖,識別出來的可信度高達0.95;而截入了背景的圖標截圖,可信度下降到了0.88。所以在截取這些特定圖標的時候,盡量減少截入背景,可以有效提高這類截圖腳本的兼容性。
2.打開應用盡量使用start_app而不是截圖腳本
start_app()
支持Android和iOS設備,相對用截圖腳本來啟動應用,腳本會更加簡潔,兼容性也會更好:
# 打開網易雲音樂 start_app("com.netease.cloudmusic")
3.用image editor查看識別結果的可信度
我們錄制/編寫好1條截圖腳本之后,無需運行,可以直接雙擊截圖,進入圖片編輯器,點擊左上角的 snapshot+recognition
按鈕,即可查看截圖在當前頁面的識別情況,包含識別出來的位置以及識別結果的可信度:
這個識別情況可以作為一個參考,幫助同學們快速調試自己的截圖腳本。
4.巧用target_pos點擊截圖的不同位置
先來了解下什么是 target_pos
。默認情況下,我們的截圖腳本都是點擊截圖的中心位置,即 target_pos=5
。對於一張截圖來說,總共有9個 target_pos
,當我們把截圖的 target_pos
設置成不同的值時,腳本會點擊在截圖不同的位置上:
雙擊IDE中的截圖即可打開圖片編輯器,右側可以修改 target_pos
的值:
修改完成之后,把截圖腳本切換成代碼模式,我們就可以看到此時的截圖腳本里面多了 target_pos
這個參數:
touch(Template(r"tpl1598948415043.png", target_pos=6, record_pos=(-0.434, -0.773), resolution=(900, 1600)))
我們在做自動化的時候,經常會遇到某個圖標堆疊的情況,比如在網易雲音樂的某個歌曲列表中,右側便羅列了三個完全一樣的播放按鈕:
如果我們的需求是點擊中間那個按鈕的,僅僅依靠截1個播放按鈕來做識別,是很難保證具體識別到三個按鈕中的具體哪個按鈕的。
此時我們可以有2種截圖方式來實現,一種是在豎着的方向上,擴大截圖范圍,讓中間那個按鈕處於 target_pos=5
的位置上:
另一種是在橫着的方向上,擴大截圖范圍把左側的歌曲介紹也一起截圖了,讓中間那個按鈕處於 target_pos=6
的位置上:
這2種方式都可以確保我們點到的是中間那個按鈕(假設列表歌曲不變的情況下)。
所以,當精准截圖(僅截取某個按鈕/圖標)不能滿足唯一定位時,我們可以考慮加大截圖范圍,增加更多的特征點,確保截圖定位的准確性。
5.巧用坐標進行點擊/滑動
有時候,我們在打開一個app時,會遇到一些過場動畫或者是幾張應用的介紹頁。這些過場動畫和介紹頁可能會隨着版本更新而變化,那么利用截圖點擊,可能需要花費我們比較大的精力去維護這些截圖腳本。
其實這時候我們完全可以用坐標點擊來替代截圖點擊,因為這些過場動畫或者介紹頁,只要有任意的點擊動作,都可以跳過。
在比如說網易雲音樂首頁的輪播圖,可能每天登錄上去都是不一樣的,如果我們用截圖腳本來滑動/點擊,那天天都需要維護這些腳本,還不如替換成坐標滑動/點擊,更加省心省力:
6.巧用keyevent("BACK")替代返回的截圖腳本
很多時候,我們需要從APP的某個頁面,回到APP首頁,一些同學可能會使用一堆的返回圖標的截圖語句,來實現這個需求:
實際上,如果同學們測的是安卓設備,完全可以用 keyevent("BACK")
來替代這個返回的截圖語句,更加穩定高效:
7.錄制功能雖好用,但也要注意截圖的兼容性
IDE自帶的錄制功能,可以幫助我們的新手同學快速上手Airtest這個基於圖像識別的測試框架,但是自動錄制出來的截圖語句,並不是都會很符合我們的實際需求,所以我們不能過度依賴錄制功能。
我們可以在錄制完畢之后,檢查下有哪些截圖並不是截的很好的,自己再手動截取一下,提升整個腳本的兼容性。
8.畫面切換的時候,可以多使用wait或者sleep,再進行點擊操作
很多新手同學都很容易犯1個錯誤,就是一不小心就寫了很多連續點擊操作;其實在每一個點擊操作之后,應用畫面也是在實時變化的。如果畫面正在加載的時候,下一個點擊操作就被執行了,就會很容易導致識別到錯誤位置或者識別超時。
舉個例子,進入網易雲音樂的app時,我們同意了服務條款之后,會有1個很長的啟動動畫,我們只有等待啟動動畫結束之后,才能夠進行下一步的點擊 “立即體驗” 的操作,否則這個點擊操作很可能因為在等待啟動動畫的過程中而識別超時:
另外,為保證連續點擊都能夠正常被執行,我們還可以在連續點擊之間用 sleep(1.0)
來緩沖下,減少畫面切換對連續點擊操作的影響。
9.合理調整闕值
上文我們就提到過闕值,它起到結果篩選的作用。也就是說,如果我們設置的闕值過低,就更容易讓錯誤的結果通過;而闕值設置得過高,就有可能把可信度達不到要求的正確結果也過濾掉,導致很難得出有效的識別結果。
所以我們可以通過合理調整闕值大小,更好地過濾出我們想要的識別結果。舉個例子,某個截圖默認闕值為0.7,但是我們多次運行之后發現,有一定概率會識別到錯誤結果。這時候我們不妨將闕值調高一點試試,看看能不能提高正確識別的概率,如果可以,說明我們的闕值調整是有效的。
在IDE種,我們可以雙擊截圖打開圖片編輯器,在右側修改截圖的闕值:
設置好並關掉圖片編輯器后,我們在腳本編寫窗口右鍵切換成代碼模式,可以看到剛才那條截圖腳本多了個 threshold=0.8
參數:
touch(Template(r"tpl1598952570968.png", threshold=0.8, record_pos=(-0.021, 0.121), resolution=(900.0, 1600.0)))
當然,我們也可以設置全局的 threshold
:
from airtest.core.setting import Settings as ST ST.THRESHOLD = 0.7 # 其他語句的默認閾值
不過上述的修改方式只適用於除斷言語句之外的截圖語句,如果在斷言語句的截圖中,雙擊進入圖片編輯器,再修改里面的 threshold
,最終也是不會生效的。因為斷言語句的闕值與其它截圖語句的闕值是不一樣的,它只能通過下述方式進行設置:
from airtest.core.setting import Settings as ST ST.THRESHOLD_STRICT = 0.7
10.用自定義語句(例如截圖列表)
對於設備長寬比不同、設備分辨率不同、多種字體的情況,我們也可以通過語法來提高兼容性。這種方式需要連接上腳本兼容性有問題的設備,把對應截圖納入搜索列表。代碼腳本如下:
picList = [pic1,pic2,pic3] # 截圖的圖片對象列表 for pic in picList: pos = exists(pic) if pos: touch(pos) break # 只要找到圖片列表中的任何一張圖片,就執行touch
注意:如果for循環中沒有break語句,會導致次邏輯運行時將所有的圖片都找一遍(找到后執行touch),而非找到合適結果立即返回。
這種情況還適用於我們想點擊任意一個隨機圖標的時候。
11.如果可以用poco框架,還可以用poco語句代替截圖腳本
如果同學們測試的項目可以使用poco框架,建議大家在自動化腳本的時候,可以靈活混用Airtest和Poco腳本,以幫助同學們的腳本達成更好的兼容性:
舉個例子,在網易雲音樂的某個歌單中,想選擇前10首歌曲,如果用截圖腳本的話,需要編寫10條截圖腳本,但如果用poco框架的話,僅需要幾行遍歷節點的腳本(以選擇前3首歌曲為例):
並且當歌曲名稱變化時,腳本截圖也需要跟着維護;這時候選擇不變的節點作為操作對象,顯然可以提升我們腳本的兼容性。
小結
提升截圖腳本兼容性的技巧就整理到這里啦,當然,除了上述技巧以外,同學們在實際的自動化過程中,可能還會總結出其它的技巧。其實這些技巧都是在多次實操的過程中總結出來的,所以只要同學們多多實踐,就會有更多更好的解決問題的思路啦!
AirtestProject官方答疑Q群:1017250147
Airtest官網:http://airtest.netease.com/
Airtest教程官網:https://airtest.doc.io.netease.com/
搭建企業私有雲服務:https://airlab.163.com/b2b