Page Object设计模式
Page object是selenium自动化测试项目开发时间的最佳设计模式之一,主要体现在对界面交互细节的封装。
1.认识page object
优点如下:
1.减少代码的重复
2.提高测试用例的可读性
3.提高测试用例的可维护性,特别是针对UI频繁变化的项目。
2.page object实例
下面以登录新浪邮箱为例,通过page object设计模式来实现。
#po_model.py
#coding:utf-8
from selenium import webdriver
from selenium.webdriver.common.by import By
import time
class Page(object):
'''基础类,用于页面对象类的继承'''
login_url='https://ui.ptlogin2.qq.com/cgi-bin/login'
def __init__(self,selenium_driver,base_url=login_url):
self.base_url=base_url
self.driver=selenium_driver
self.timeout=30
def on_page(self):
return self.driver.current_url==(self.base_url+self.url)
def _open(self,url):
url=self.base_url+url
self.driver.get(url)
assert self.on_page(),"Did not land on %s" % url
def open(self):
self._open(self.url)
def find_element(self,*loc):
return self.driver.find_element(*loc)
class LoginPage(Page):
'''新浪邮箱登录页面模型'''
url='/'
#定位器
username_loc=(By.ID,"u")
password_loc=(By.ID,"p")
submint_loc=(By.ID,"go")
#Action
def type_username(self,username):
self.find_element(*self.username_loc).send_keys(username)
def type_password(self,password):
self.find_element(*self.password_loc).send_keys(password)
def submit(self):
self.find_element(*self.submint_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.submit()
def main():
try:
driver=webdriver.Chrome()
username='xxxxxxxx'
password='xxxxxxxxxx'
test_user_login(driver,username,password)
time.sleep(10)
text=driver.find_element_by_class_name("qm_toolbarTitle").text
assert(text == u'xxxxxxx - 退出'),u"用户名称不匹配,登录失败!"
finally:
#关闭浏览器窗口
driver.close()
if __name__=='__main__':
main()
Page object设计模式的实现方法显然使结构变得复杂了很多,下面对其逐段分析,来体会这样设计的好处。
1.创建page类
class Page(object): '''基础类,用于页面对象类的继承''' login_url='xxxxx' def __init__(self,selenium_driver,base_url=login_url): self.base_url=base_url self.driver=selenium_driver self.timeout=30 def on_page(self): return self.driver.current_url==(self.base_url+self.url) def _open(self,url): url=self.base_url+url self.driver.get(url) assert self.on_page(),"Did not land 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地址的断言部分,则交给on_page()方法来实现,而find_element()方法用于元素的定位。
2.创建LoginPage()类
Page类中定义的这些方法都是页面操作的基本方法,下面根据登录页的特点再创建LoginPage类并继承Page类,这也是Page Object设计模式中最重要的对象层。
class LoginPage(Page): '''新浪邮箱登录页面模型''' url='/' #定位器 username_loc=(By.ID,"u") password_loc=(By.ID,"p") submint_loc=(By.ID,"go") #Action def type_username(self,username): self.find_element(*self.username_loc).send_keys(username) def type_password(self,password): self.find_element(*self.password_loc).send_keys(password) def submit(self): self.find_element(*self.submint_loc).click()
LoginPage类中主要对登录页面上的元素进行封装,使其成为更具体的操作方法。例如:用户名、密码和登录按钮都被封装成了方法。
3.创建test_user_login()函数
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.submit()
test_user_login()函数将单个的元素操作组成一个完整的动作,而这个动作包含了打开浏览器、输入用户名/密码,点击登录等单步操作。在使用该函数时需要将driver、username、password等信息作为函数的入参、这样该函数具有极强的可重用性。
4.创建main()函数
def main(): try: driver=webdriver.Chrome() username='xxxxx' password='xxxxx' test_user_login(driver,username,password) time.sleep(10) text=driver.find_element_by_class_name("qm_toolbarTitle").text assert(text == u'xxxxx - 退出'),u"用户名称不匹配,登录失败!" finally: #关闭浏览器窗口 driver.close() if __name__=='__main__': main()
main()函数更接近与用户的操作行为。对用户来说,要进行邮箱的登录,需要关心的就是通过哪个浏览器打开邮箱地址、登录的用户名和密码是什么,至于输入框、按钮是如何定位的,则不需要关心。
这样分层的好处:不同的层关心不同的问题,页面对象层只关心元素的定位问题,测试用例只关心测试的数据。
章小结:
介绍了三个知识点:利用HTMLTestRunner生成测试报告、集成自动发邮件功能和page object设计模式,虽然他们之间没有直接的联系,但是合理化的运行到自动化测试项目中将有助于自动化测试项目的开展。