1. 程式人生 > >WEB-UI自動化測試實踐

WEB-UI自動化測試實踐

 

一、設計背景

隨著IT行業的發展,產品愈漸複雜,web端業務及流程更加繁瑣,目前UI測試僅是針對單一頁面,操作量大。為了滿足多頁面功能及流程的需求及節省工時,設計了這款UI 自動化測試程式。旨在提供介面,整合到蝸牛自動化測試框架,方便用例的設計。

整個程式是基於 selenium 設計的。程式對 selenium 提供的介面進行了二次封裝以滿足日常的用例設計,二次封裝後的介面解決了元素載入,元素定位解析等問題,可以讓用例設計變得更加簡捷。

之所以採用 Selenium 的模式。原因一,對於使用者來說這是一個開源框架,很想窺探一二; 原因二,Selenium 可無縫接入。這是一個用於Web應用程式測試的工具,支援多平臺、多瀏覽器、多語言去實現自動化測試,Selenium2將瀏覽器原生的API封裝成WebDriver API,可以直接操作瀏覽器頁面裡的元素,甚至操作瀏覽器本身(截圖,視窗大小,啟動,關閉之類的),所以就像真正的使用者在操作一樣。

目前支援:Mac、Windows作業系統,chrome、Firefox、IE瀏覽器。

二、工作原理

  • 在蝸牛管理後臺新增測試用例。
  • 蝸牛管理後臺測試用例執行呼叫任務執行介面,傳送任務id及測試資料的JSON格式字串給程式。
  • 程式根據獲取資料,解析並處理。
  • 啟動瀏覽器後,selenium-webdriver會將目標瀏覽器繫結到特定的埠,啟動後的瀏覽器則作為webdriver的server。
  • 客戶端(也就是測試指令碼),藉助ComandExecutor傳送HTTP請求給server端(通訊協議:The WebDriver Wire Protocol,在HTTP request的body中,會以WebDriver Wire協議規定的JSON格式的字串來告訴Selenium,我們希望瀏覽器接下來做什麼事情)。
  • Server端需要依賴原生的瀏覽器元件,轉化Web Service的命令為瀏覽器native的呼叫來完成操作。
  • 最後將處理結果及任務id通過JSON字串的格式返回給蝸牛,通過蝸牛的管理後臺可檢視每條用例執行結果。

三、框架介紹

3.1 工程結構

按照實際的業務流程呼叫對應介面來實現 WEB-UI 自動化測試用例。case 層可呼叫 service 層和 pageObject 層的介面,pageObject 是對每一個頁面元素的一個封裝,service 是對一個常用的業務模組功能的封裝。比如一個查詢企業資訊的測試用例,需要依賴登入,這個業務功能就可以直接呼叫 service 中的介面。企業查詢的建立就可以呼叫 pageObject 中的介面,然後按照查詢的業務流程,在測試用例中把這些介面串起來就形成了一個 UI 自動化測試用例,詳細細節接下去會舉例說明。

如企業查詢。查詢之前,需要登入管理後臺,登入操作已封裝到業務層,直接呼叫 service 層的介面,不需要在意這個步驟的細節;登入之後要指定一個路徑,找到對應的空間,直接呼叫 model 層的介面,不需要在意這個步驟的細節;接著是建立查詢,建立查詢的所有定位方法也封裝到業務層,這就是個企業查詢的實現,也是用例設計中最主要的環節。

整個工程基於 selenium,採用 pageObject 模式搭建。下面對工程中的幾個重要模組做介紹。

3.1.1 driver — 介面層

對 web 頁面所有元素的操作都是在driver定義介面並實現的。driver 對 selenium 提供的介面做了二次封裝,對外提供封裝後的介面。pageObject 實現了一些公共方法,比如給輸入框賦值等,目前 pageObject封裝的方法不多,大多功能都可以通過 selenium 實現。driver 層對開源工具介面做了二次封裝,想要驅動一個瀏覽器還有一個必不可少的工具 —— 瀏覽器驅動,這個驅動放在 Referenced Libraries 裡,驅動的版本必須與被測瀏覽器版本相匹配。

3.1.2 model — 資料模型

建立資料模型為了實現測試資料和測試用例分離而採取的一種方法,具體的測試資料初始化。可以對一個業務流程中需要測試資料的元素在一個 model 中定義出來,方便管理和程式碼閱讀。

3.1.3 pageObject — 業務層

pageObject 模式,採用介面形式封裝每一個頁面需要用到的元素,實現封裝只要做兩步:

  • 確定元素的定位方式;
  • 呼叫 driver 中對應的操作介面。

driver 的介面實現包含了一定的容錯能力,但並不是全面的,部分頁面或者元件具有獨特性,單純呼叫 driver 的介面並不能保證測試用例的穩定性,此時就需要在 pageObject 的介面實現中加入一些容錯演算法,確保用例穩定性。

3.1.4 service — 提供業務功能

一個業務流程很多時候依賴其他業務模組功能,為了方便設計一個測試用例,也為了避免重複造輪子,service 層就提供了一些常用的業務功能,比如登入、企業查詢等。依賴方只需要在 service 層呼叫即可。

3.2 功能優化

對selenium 做二次封裝的同時也對介面做了優化,框架的初衷是使UI 用例的設計儘可能的易設計、易讀、易維護。

3.2.1 介面優化

直接呼叫 selenium 的介面經常會遇到些令人頭疼的問題,比如網路問題使頁面 loading 太慢,需要操作的元素還沒展示出來,這種情況就會經常報元素找不到的 error,導致用例執行失敗,但實際上這種報錯並不是一個 bug,其測試結果是無效的。為了減少誤報率 driver 層介面設計了等待元素載入的功能,使用的關鍵方法:cf.searchForElementVisibleXpath(TestStartQuitwd.wd, "//*[text()='運營平臺登入']", id, 200, 100L)。參考程式碼:

在 click、input 等操作介面中加入迴圈查詢的判斷可最大限度的等待一個元素的載入從而提高測試用例的穩定性。

3.2.2 元素定位統一入口

接觸過 UI 自動化用例設計的測試人員會比較清楚,想通過 selenium 操作一個元素,其中必不可少的就是對元素定位的描述,通俗的講就是要通知介面在當前頁面操作哪個位置上的元素。定位一個元素的方法很多,常用的有 id,name,css,xpath 等,對應不同的定位方法selenium 在處理上也給出了不同介面,這從維護角度上來考慮顯然不是最好的。最好的做法就是用例設計者只管元素定位和操作事件的呼叫,而事件在實現上走了哪種渠道最好是無感知,無需維護的。對此框架封裝了一個方法供 driver 呼叫,主要功能就是解析描述元素的字串自動判斷是 id、css 還是 xpath。

3.3 元素定位

UI自動化用例其實可以分成兩部分:定位元素;呼叫介面操作該元素。其中定位一個元素的方法很多,常用的有 id,name,css,xpath。實際設計中選擇哪種定位方法一般會在維護角度上考慮的會多一些,因為現在的伺服器效能配置等都很優秀,所以跑一個WEB-UI用例可以不用考慮效能問題。從維護成本上考慮會優先選擇 id、name,其次 css,最後用 xpath。

我們不能保證每一個 web 系統的所有元素都能提供一個唯一 id 或 name,當然如果能和前端開發達成合作,這就是一件很美好的事情了。一般情況下我們都需要面對沒有 id 和 name 這兩個屬性的情況。這時我們就可以使用 css 樣式,很多時候 css 樣式是能滿足我們的定位需求。當然在這些都不提供給我們的情況下就只能選擇 xpath,使用 xpath 的優點:

  • 易獲取,主流瀏覽器只要開啟“檢視”就可以通過 copy 輕鬆獲取到;
  • 頁面上的元素都可以用 xpath 來描述;缺點,不穩定,大量使用會給用例維護產生很大的負擔。

xpath 一般只要前端在頁面上做一下小調整,用例就必須重新維護,在不得不使用 xpath 的情況下,為了減少今後的維護量,可對 xpath 做一些優化,可以減少 xpath 的路徑長度提高穩定性。以下是實踐過程中最長用到的幾種型別:

  • 依靠自己的屬性文字定位,如 //input[@value=‘XXXXX’]
  • 包含指示性字元,如 //input[contains(text(),’指示性字元’)]
  • 巧妙使用content,如 //*[@id=‘app-container']

四、常見報錯

使用過程中經常會遇到問題,這裡做下總結方便 debug。

  • 某些頁面彈窗,有時候定位不到彈窗元素。理論上 selenium 在一個頁面中查詢一個元素是可以定位到,但有些時候出現彈窗,此時就需要在重新定位彈窗。解決方法:

  • 有些輸入框不能被 input 介面正常操作。實踐過程中在日曆控制元件中遇到過,元素定位什麼的都對,但就是不能正常被操作。解決方法:判斷元素是否是select型別,之後再賦值。解決程式碼:

3.發現 selenium 的某些介面不能 work 了,此時最大的可能就是瀏覽器升級了。解決方法:重新下載低版本瀏覽器。

4.元素不可見。有一種元素能在頁面上正常展示,但對於工具來說它是不可見的,這是因為在一般情況下,元素可見需要滿足以下幾個條件:visibility!=hidden ; display!=none; opacity!=0; height、width都大於0;對於 input 標籤,沒有 hidden 屬性。如截圖就是隻讀的例項。

解決方法:呼叫介面 TestStartQuitwd.js.executeScript("var txtN = document.getElementsByName("timeRange"); txtN[0].readOnly = false;"); 

五、結束語

UI自動化是在開源工具的基礎上做了些優化,在 driver 層,資料層、業務層以及用例層的解決方案還有很大的提升空間。WEB-UI自動化還不完美,後期還需繼續努力。感謝一直以來支援研究的小夥伴。

作者:顏博蓮

來源:宜信技術