Page Object
Page Object 模式是selenium自动化测试项目开发最佳测试设计模式,主要体现在对界面交互细节的封装,这样使得测试案例更加注重页面而不是界面细节,提高了测试用例的可读性。
Page Object模式主要是将每个页面设计为一个类class,这个类包含页面中需要测试的元素(按钮、输入框、URL、标题等)和实际操作方法,这样在写测试用例时可以通过调用页面类的方法和属性来获取页面元素和操作元素,这样优点是避免当页面元素的ID或位置改变时需要更改测试用例代码的情况。当页面元组定位发生改变时只要通过更改页面类的属性即可。
一个类中,一个方法调用另一个方法时,需要加self.被调用的方法(self.入参) 在Python方法中入参是元组时,需要加*,因为Python存在这种特性,将入参放进元组里,入参是元组的元素需要加*。 把操作方法封装为函数时,return返回就是这个操作方法的具体操作,return返回值可以给其他函数直接使用的。 Page Object的优点
提高测试用例的可读性; 减少了代码的重复; 提高测试用例的可维护性,特别是针对UI频繁变动的项目。
page object使用例子 base.py
定义页面基础类,用于所有页面的基础,封装所有测试页面的公共方法。
[python] view plain
class Page():
'''''基础类,用于所有页面的继承''' login_url = "" #实例化Page类时会执行__init__方法,该方法的入参是Page类的入参 #init()构造函数不能只能返回None def init(self,driver,base_url=login_url): self.driver = driver self.base_url = base_url self.timeout = 30 #on_page()方法是URL地址的断言部分 def on_page(self): return self.driver.current_url == (self.base_url+self.url) #单下划线_开头表示是私有的,就是通过import时私有的方法不会被导入 #_open()方法用于打开URL网站,并检验页面链接加载是否正确 def _open(self,url): url = self.base_url +url self.driver.get(url) assert self.on_page(),"Did not land on %s" %url #open()方法通过调用_open()方法打开URL网站 def open(self): self._open(self.url) #重写定位元素的方法,loc==(By.NAME,"email"),是一个元组,Python方法中入参是元组时需要在前面加 def find_element(self,*loc): return self.driver.find_element(*loc) def find_elements(self,*loc): return self.driver.find_elements(*loc)login_object.py
每个测试页面元素定位和操作方法都在这层定义,一单UI发生改变只需要在该层修改对象属性即可。
[python] view plain
from time import sleep
from .base import Page from selenium.webdriver.common.by import Byclass Login_Page(Page):
'''''登录页面模型''' url = "/" #定位器,定位需要用到的元素,元组 username_loc = (By.NAME,"email") password_loc =(By.NAME,"password") submit_loc =(By.XPATH,"//[@id='dologin']") #action,把每个操作封装为一个方法 def switch_frame(self): return self.driver.switch_to.frame("x-URS-iframe") #账号输入框的操作方法 def type_username(self,username): return self.find_element(self.username_loc).send_keys(username) #密码输入框的操作方法 def type_password(self,password): return self.find_element(self.password_loc).send_keys(password) #提交按钮操作方法 def type_submit(self): return self.find_element(self.submit_loc).click() #写一个同一登录的入口,考虑到其他用例也会调用该登录方法,入参设置了默认值是为了方便其他用例在调用该方法登录时不用在传登录用户信息。 def user_login(self,username="testXXXst1",password="yuXXX336.."): self.open() self.switch_frame() self.driver.implicitly_wait(10) self.type_username(username) self.type_password(password) self.type_submit() sleep(5) #定位器:错误提示 username_null = (By.XPATH,"//[@id='login-form']/div/div[7]/div[2]") password_null = (By.XPATH,"//[@id='login-form']/div/div[7]/div[2]") password_error =(By.XPATH,"//[@id='login-form']/div/div[7]/div[2]") login_success = (By.XPATH,"//[@id='dvContainer']/div/div/div/div[2]/div[2]/span/span") #用户名空提示 def type_username_null(self): return self.find_element(*self.username_null).text #密码空提示 def type_password_null(self): return self.find_element(*self.password_null).text #密码和用户名不匹配提示 def type_username_or_pwd_error(self): return self.find_element(*self.password_error).text #登录成功 def type_login_success(self): return self.find_element(*self.login_success).text下面通过unittest框架编写测试用例
login_test.py
[python] view plain
from email_login import Login_Page
from selenium import webdriver import unittestclass Test_login_model(unittest.TestCase):
def setUp(self): #浏览器驱动 self.driver = webdriver.Firefox() #实例化 self.login_page = Login_Page(self.driver) def tearDown(self): self.driver.quit() #因为user_login_verify()设置了默认值,这里重新将其入参的默认值设置为空。 def user_login_verify(self,username="",password=""): self.login_page.user_login(username,password) #编写测试用例,必须test*格式 def test_login1_success(self): '''''测试用例1:登录成功''' self.user_login_verify(username="test0_test1",password="yue1048355336..") #装饰器直接跳过该测试用例 @unittest.skip("不需要运行") def test_login2_username_null(self): '''''测试用例2:用户名空,密码正确''' self.user_login_verify(password="yue1048355336..") def test_login3_password_null(self): '''''测试用例3:用户名正确密码为空''' self.user_login_verify(username="test0_test1") def test_login4_null(self): '''''测试用例4:用户名密码都为空''' self.user_login_verify() def test_login5_password_error(self): '''''用户名正确密码错误''' self.user_login_verify(username="teXXXest1",password="yueXXX336")if name == "main":
unittest.main()结论:
页面对象只关心元素定位和操作方法封装问题,测试用例只需要关心测试就行。