頁面對象(Page Object)模式是目前自動化測試領域普遍使用的設計模式之一,此模式可以大大提高測試代碼的復用率,提高測試腳本的編寫效率和維護效率,是中級自動化測試工程師的必備技能之一。
1.頁面對象模式簡介
自動化測試腳本除了在一定程度上難編寫,還有一個巨大的挑戰,就是如何盡量減少維護的成本。大量的腳本因為難以維護,導致測試人員不得不再次投入大量資源去重新編寫新的測試腳本,以滿足日新月異的需求調整和變化。自動化測試腳本的巨大維護成本不僅會造成大量的人力投入,還會導致測試需求無法被快速響應,長此以往,會嚴重阻礙自動化測試在項目中的深入實施。
為了盡量解決上面的窘境,自動化測試腳本需要使用一些設計模式來降低測試腳本的工作量,提高自動化測試的投入產出比,延長自動化測試腳本的服務和工作周期。WebDriver提供了頁面對象模式來提高自動化測試腳本的可維護性,此模式已經廣泛應用於自動化測試領域。
使用面向對象的設計模式,頁面對象模型將測試代碼和被測試頁面的頁面元素及其操作方法進行分離,以此降低頁面元素變化對測試代碼的影響。每一個被測試頁面都會被單獨定義為一個類,類中會定位所有需進行測試操作的頁面元素對象,並且定義操作每一個頁面元素對象的方法。
例如,登錄頁面包括一個用戶輸入框和一個密碼輸入框,還有一個登錄按鈕。
我們聲明一個名為Login的類,並且通過定位表達式找到用戶名和密碼輸入框,並賦予類中的成員變量,分別定義輸入用戶名的方法、輸入密碼的方法和單擊登錄按鈕的方法。
測試代碼要完成登錄測試,只需要調用Login類中輸入用戶名的方法、輸入密碼的方法和單擊登錄按鈕的方法即可完成一個登錄操作。如果登錄頁面的用戶輸入框、密碼輸入框或者登錄按鈕發生了位置變化,我們只需要修改Login類中的相關定位表達式和操作方法就可以完成維護,測試邏輯的腳本甚至不需要改變。
如果用戶沒有使用此模式,那么將登錄過程都用相同的代碼進行實現。如果在測試過程中需要多次登錄操作,那么只能粘貼相同的代碼來簡化編寫工作。但是可怕的情況是一旦頁面元素發生了一點點改變,那么測試人員需要人工去把所有涉及變化的邏輯一一修改,會在不同的測試代碼中進行搜索和修改,這樣不但大大增加了工作量,而且很容易出現修改錯誤的情況。使用了頁面對象模式,只需要修改一下唯一的Login類,就完成了大部分的維護工作。
2.使用PageFactory類
(1)使用PageFactory類給測試類提供待操作的頁面元素
首先在src中新建一個package,名字為pageobjects,在下面新建一個頁面對象類LoginPage。新建一個package,名字為testScripts,在下面新建一個測試類Test126mail。
LoginPage類的源代碼如下:
Test126mail類的源代碼如下:
從上面的實例中我們可以看到,頁面元素的定位均在LoginPage類中實現了。如果頁面元素發生了一定程度的調整,測試人員只需要修改LoginPage類中的定位表達式就可以完成基本的維護工作,測試類代碼無需進行調整,從而降低了測試代碼的維護工作。
(2)使用PageFactory類封裝頁面元素的操作方法
上面我們只為測試類提供了頁面元素來進行操作,並沒有在頁面對象類中實現頁面元素的操作方法。
LoginPage類的源代碼如下:
Test126mail的源代碼如下:
在頁面對象中封裝了頁面元素的操作方法,使得在測試代碼中實現測試邏輯更加容易。這些封裝方法可以被很多測試邏輯重復調用,從而提高了代碼編寫和維護的效率,實現了一個類維護,很多測試類可被調用的目的,進一步降低了測試代碼的維護成本。
(3)使用LoadableComponent類
繼承LoadableComponent類可以在頁面加載的時候判斷是否加載了正確的頁面,只需要重寫isLoaded和load兩個方法。此方式有助於讓頁面對象的頁面訪問操作更加健壯。
LoginPage類的源代碼:
Test126mail類的源代碼:
(4)多個PageObject的自動化測試實例
本節主要講解多個PageObject的使用方法,以及如何基於多個PageObject實現一個相對復雜的自動化測試實例。
自動化測試實現的3個測試用例如下:
a.在126郵箱,使用正確的用戶名和錯誤的密碼進行登錄,登錄失敗並在頁面顯示“帳號或密碼錯誤”關鍵字。
b.在126郵箱,使用正確的用戶名和正確的密碼進行登錄,登錄成功后會跳轉到郵箱文件夾列表首頁,並且顯示出“收件箱”關鍵字。
c.在126郵箱,登錄成功后,單擊“寫信”鏈接,給testYY2017@126.com發送一封郵件,郵件發送成功后頁面顯示“發送成功”關鍵字。
LoginPage類:
HomePage類:
SendSuccessPage類:
Test126mail類
3.設計原則
(1)在PageObject類中定義public方法來對外提供服務。
(2)不要暴露PageObject類中的內部邏輯。
(3)不要在PageObject類中進行斷言操作。
(4)只需要在PageObject類中定義需要操作的元素和操作方法。
(5)PageObject頁面中的相同動作如果會產生多個不同的結果,需要在PageObject類中定義多個操作方法。