如何提高UI自動化測試的質量

背景

??????項目是基于Ruby on Rails開發(fā)的web程序,應該說項目中的測試實踐是很好的,具有高覆蓋率的單元測試以及比較合理的集成測試。存在的問題是,所有的單元測試和集成測試都是針對后端代碼的,前端的JavaSript代碼沒有單元測試(這個是有歷史原因的,暫時沒法改變)。這也就意味著針對前端UI的修改是沒有底層的單元測試來保障的,只能依靠高層級的UI自動化測試和手工測試來保障。

??????我們最近剛剛完成了一個story,是純前端的開發(fā)工作,結果在上線后發(fā)現我們在修改頁面模板文件時,忘記了其他地方也在使用同樣的模板文件,導致了部分頁面樣式錯亂,甚至無法訪問。這個bug在現有的UI自動化測試和手工測試中都被遺漏了,直接發(fā)布到了產品環(huán)境上,后來通過線上日志才被發(fā)現。不得已我們只好把版本先回退,修復bug后再重新上線,release的時間推遲了一周,可以說整個團隊為此付出了嚴重的代價。

痛點

? ? ??作為團隊的QA,出現這樣的問題自然讓我很不好受,顏面無光。。。拋開沒有做story業(yè)務分析,手工測試場景遺漏等問題,聚焦在現有的UI自動化測試上,以下是我感知到的一些痛點:

UI自動化測試的穩(wěn)定性不高 - UI自動化測試是用ruby版本的selenium實現的,存在著眾所周知的問題,例如不夠穩(wěn)定,經常由于頁面加載超時,UI交互復雜等問題導致測試失敗,使得自動化測試結果的有效性不高,失去了它本來應該具有的價值。

測試場景覆蓋不夠全面 - 當然,根據測試金字塔的理念,上層的UI自動化測試應該是小規(guī)模的,只覆蓋基本功能:

??????但是具體到這個項目中,由于前端代碼的底層測試缺失,所以不得不依靠高層級的UI自動化測試來覆蓋更多的場景, ? 最起碼要能完成基本的回歸測試,否則手工測試的壓力太大。這就回到了第一個問題,正是由于UI自動化測試的穩(wěn)定性不高,所以我只實現了很小一部分功能,以免后續(xù)維護的成本太高,而我們遺漏的bug恰恰沒有包含在自動化測試的場景中。

問題分析

? ? ??所以,我們的聚焦點集中在了如何提高UI自動化測試的質量上,經過分析,主要的問題有:

頁面加載時間超時

在用webdriver的方法訪問頁面時,經常出現加載超時的問題。頁面的DOM結構已經渲染完成了,但是在訪問某些外部網站時長時間沒有響應,導致測試腳本一直卡著無法繼續(xù)進行,最后報超時錯誤。

頁面交互action太多

UI自動化測試的一個缺點就是所有的執(zhí)行動作都要通過頁面的action來完成,例如文本框輸入,點擊按鈕,而且這些動作的執(zhí)行結果存在太多的變數,導致最后寫出來的測試腳本太過脆弱,很容易失敗。

解決問題

使用異常捕獲機制來處理超時等異常情況

??????針對頁面超時的問題,由于頁面的DOM結構已經渲染完成了,所以其實可以繼續(xù)執(zhí)行后續(xù)的用例。但是如果與外部網站的請求沒有全部完成,selenium會認為頁面加載沒有完成,就一直卡在訪問頁面的get方法上。我的做法是設定一個頁面加載的超時時間:

dr.manage.timeouts.page_load = 30

??????超過30秒就認為頁面加載超時(經過測試,30秒的時間已經足夠把頁面的DOM結構渲染完成了),然后訪問頁面時捕獲超時的異常:

begin

? ?page.open_page

rescue Selenium::WebDriver::Error::TimeOutError

???puts "ERROR:page load timeout!!"

end

??????這樣如果加載超過30秒,會拋出異常后繼續(xù)向下執(zhí)行。不致于因為訪問某些外部網站請求過慢,而卡在頁面加載的步驟,導致整個測試用例失敗。同樣的策略也可以應用在某些復雜或者不確定的執(zhí)行結果上,捕獲可能出現的異常,提高測試的健壯性,避免非產品原因導致的測試用例失敗。

減少UI測試,增加API級別的測試

這個觀點聽上去多少有點荒唐,提高UI測試質量的方法是減少UI測試。。。。但事實就是這樣,UI測試是自動化成本最高,最不穩(wěn)定的測試,能夠在低層級完成的測試,例如API層的測試,就不要放到UI層去完成,這樣會使測試更加穩(wěn)定和健壯。很多頁面action,例如提交表單,點擊按鈕等,實際都是向后臺發(fā)送了一條請求,如果測試的是功能,那么完全可以用API來完成這些測試。重點還是在于我們究竟想測什么,是否必須要從UI層去完成這些測試?這就是測試結構的設計問題了,這里不展開討論。

在這個項目中,我把一些可以在API層完成的測試從UI測試用例中分離出來,用ruby的Faraday庫(當然也可以用其他的,例如JS的SuperTest)調用相應的API并對返回數據做校驗,這些測試相比于UI測試更加穩(wěn)定,運行速度更快,整個測試的穩(wěn)定性便得到了提升。

將頁面交互的action與靜態(tài)頁面內容分開測試

這個方法的思路和上一個類似,盡量減少通過頁面加載和交互來完成的測試。如果測試內容中不包含動態(tài)的頁面交互步驟,例如只是想測試頁面能否正常打開,某一部分的內容能否正常顯示等,可以從頁面的DOM結構中通過校驗某些元素來完成測試。

舉個例子,如果想測試百度首頁,可以不用從selenium webdriver中去加載這個頁面,直接用ruby的Faraday或者JS的SuperTest去訪問"http://www.baidu.com"這個URL。這樣拿到的將是一段html的文本,然后再解析這段html文本(例如用ruby的Nokogirl庫),獲取對應的內容來做校驗。例如返回碼是200,<title>的內容是“百度一下,你就知道”,那么可以認為首頁能夠正常打開。<img>中的src屬性是一個正確的圖片文件,可以認為百度的logo能夠正常顯示。

這里會產生疑問,如果我就是想測試界面怎么辦?這就回到了剛才那個問題,我們究竟想測什么?如果只是想測功能,那么我們就盡量減少對界面的依賴。如果只是想測界面,那么也有其他的辦法來完成,例如WebdriverCSS或者PhantomCSS等界面對比的測試工具。當然,有些測試步驟是必須要依賴頁面交互的,例如點擊某個按鈕打開一個新的對話框或者跳轉到其他頁面,這些測試就只能通過webdriver來完成了。

總結

??????通過實際的嘗試,我明顯感覺到優(yōu)化后的自動化測試相比于原來有了更穩(wěn)定的表現,運行速度變快,非產品原因導致的用例失敗次數變少。而且自動化測試更穩(wěn)定后,我有信心去實現更多的自動化測試,擴大覆蓋的場景。我的一些感受和收獲是:

  1.UI自動化測試的編碼實現不難,難的是如何做整體的測試結構設計。在UI測試中覆蓋的場景太少達不到測試的目的,場景太多又會成為團隊的負擔,帶來高昂的維護成本,需要和UT/API等測試綜合考慮,互相彌補。

  2.UI自動化測試是把雙刃劍,它應該是QA最后考慮的自動化測試方法。只有當其他層級的測試無法達到目的,或者希望測試的內容必須要通過UI完成時,再去考慮用它。低層級能完成的測試不要放在高層級去完成,在靜態(tài)DOM結構中能完成的測試不要通過webdriver加載頁面去完成。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容