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更接近用户的操作行为。对用户来说,要进行网站的登录,需要关心的就是通过哪个浏览器打开网站网址,登录的用户名和密码是什么。
这样分层的好处是,不同的层关心不同的问题,页面对象层只关心元素的定位问题,测试用例只关心测试的数据