Page Object是Selenium自動化測試項目開發實踐的最佳設計模式之一,通過對界面元素和功能模塊的封裝減少冗余代碼,同時在后期維護中,若元素定位或功能模塊發生變化,只需要調整頁面元素或功能模塊封裝的代碼,提高測試用例的可維護性。
案例:登錄帝國網站(http://localhost)
首先定義一個基礎類,用於頁面對象的繼承
BasePage.py
from time import sleep class Page(): '''頁面基礎類''' # 初始化 def __init__(self, driver): self.driver = driver self.base_url = 'http://localhost' self.timeout = 10 # 打開不同的子頁面 def _open(self, url): url_ = self.base_url + url print("The url is %s" % url_) # self.driver.maximize_window() self.driver.get(url_) sleep(2) assert self.driver.current_url == url_, 'Did not load on %s' % url_ def open(self): self._open(self.url) # 元素定位方法封裝 def find_element(self, *loc): return self.driver.find_element(*loc)
代碼分析:
首先創建一個基礎類Page,在初始化方法__init__()中定義驅動(driver),基本的URL(base_url)和超時時間(timeout)等
定義Open()方法用於打開URL網站,但它本身並未做這件事情,而是交由_open()方法來實現。關於URL地址的斷言方法,則交由assert實現,而find_element()方法用於元素定位
之后設計網站登錄頁面模型
LoginPage.py
from BasePage import * from selenium.webdriver.common.by import By class LoginPage(Page): url = "/" # 定位器 username_loc = (By.NAME, 'username') password_loc = (By.NAME, 'password') submit_loc = (By.NAME, 'Submit') # 用戶名輸入框元素 def type_username(self, username): self.find_element(*self.username_loc).clear self.find_element(*self.username_loc).send_keys(username) # 密碼輸入框元素 def type_password(self, password): self.find_element(*self.password_loc).clear self.find_element(*self.password_loc).send_keys(password) # 登錄按鈕元素 def type_submit(self): self.find_element(*self.submit_loc).click # 登錄功能模塊封裝 def test_user_login(driver, username, password): '''測試用戶名密碼是否可用''' login_page = LoginPage(driver) login_page.open() login_page.type_username(username) login_page.type_password(password) login_page.type_submit()
代碼分析:
Page類中定義的這些方法都是頁面操作的基本方法。上面根據再登錄頁面的特點再創建LoginPage類並繼承Page類
LoginPage類中主要對登錄頁面上的元素進行封裝,使其成為更具體的操作方法,例如用戶名,密碼和登錄按鈕都被封裝成了方法
test_user_login()函數將單個的元素操作組成一個完整的動作,而這個動作包含了打開瀏覽器,輸入用戶名\密碼,點擊登錄等單步操作。在使用該函數時需要將driver、username、password等信息作為函數的入參,這樣該函數具有很強的可重用性
最后將用戶名和密碼傳進去
login_test.py
from LoginPage import * from selenium import webdriver driver = webdriver.Firefox() username = '用戶名' password = '密碼' test_user_login(driver, username, password) sleep(3) driver.quit()
login_test更接近用戶的操作行為。對用戶來說,要進行網站的登錄,需要關心的就是通過哪個瀏覽器打開網站網址,登錄的用戶名和密碼是什么。
這樣分層的好處是,不同的層關心不同的問題,頁面對象層只關心元素的定位問題,測試用例只關心測試的數據