page object 是一种分层的思想,用户并不关心是如何找到元素的,用户只是进行输入,提交这些操作而已,如何让代码进行合理的分层,使得更加接近用户的行为,而隐藏掉一些定位的细节,更参数化,使得代码复用性更高,提高测试用例的可读性以及用例的可维护性
当web页面编写测试用例时,需要操作web页面上的元素,然而如果在测试代码中直接操作HTML元素,那么这个代码是非常脆弱的,UI是经常变动的,用page对象封装成一个HTML页面,里面包含定位元素,并封装成接口提供给测试用例进行调用,这样在最终的测试用例中无需在HTML中寻找,只是调用接口而已,一旦变动,测试用例的逻辑是不变的,调用的函数还是那个,只是那个函数定位的元素变了而已
不是page_object模式把定位元素和测试方法按照过程式的写下来,而page_object设计过的代码则是把定位元素与测试方法分离,用户关心的是classB,而classA对于用户是黑盒的,但它给classB提供接口
page并不一定是一个页面,更加合理的解释是通过给“页面”建模,使其对测试方法变得更有意义,如登录框需要输入用户名和密码和登录操作
non_page_object
driver.find_element_by_name("uid")driver.find_element_by_name("password")driver.find_element_by_name("submit").click()
page_object
import login_pagedef test_login(username, password): login_page.SetUsername(username) login_page.SetPassword(password) login_page.Submit()
test_login就是接口提供给测试用例调用的接口,可以更改 username,password进行关键字驱动,页面对象层只关心元素定位的问题,测试用例只关心测试的数据,如username,password通过这样的设计,如果webUI中的登录locator变了,我们只需要改动login_page,而对于测试用例则不变,无论UI如何变化,登录的流程是不会变的,输入用户名,密码,提交,这就是分层
下面介绍一个实例来说明page_object的设计
打开网页 http://demo/guru99.com/v4/获取网页title, 判断是否在一个登录页面上输入用户名输入密码登录获取网页中的一个登录成功的元素中的文本,验证是否登录成功
non_page_object_login
#!/usr/bin/env pythonfrom selenium import webdriverfrom selenium.webdriver.support.ui import WebDriverWaitdriver = webdriver.Firefox()driver.implicitly_wait(10)#open pagedriver.get("http://demo.guru99.com/v4/")#find check point about login_pagehomeText = driver.find_element_by_xpath("//div[1]/h2").text#judge client open login_page successfulassert homeText == "Guru99 Bank", 'cannot go to login page'#set usernamedriver.find_element_by_name("uid").send_keys("mngr44067")#set passworddriver.find_element_by_name("password").send_keys("etUtamE")#submitdriver.find_element_by_name("btnLogin").click()#get text about valid user infohometext = driver.find_element_by_xpath("//table[1]/tbody/tr[3]/td").text#judge user login successfulassert hometext == "Manger Id : mngr44067", "invalid user"#invalid user and pop alert to accepttry: driver.switch_to_alert().accept()except: pass#verify go back to home pageassert homeText == "Guru99 Bank", "no found"driver.close()
红色标出来的就是检查点,这个代码是非常脆弱的,如果换一个用户名,就要重写,如果webUI变动一下,这个代码就要修改
page_object分离webElement,test_case,根据页面进行分离,首先是登录页面,之后是成功登录后的页面,分别定义,最后再根据用户思想进行测试用例编写
page_login.py
#!/usr/bin/env pythonfrom selenium import webdriverfrom selenium.webdriver.common.by import Byclass Guru99Login(object): #Locator user = (By.NAME, "uid") password = (By.NAME,"password") homeText = (By.XPATH,"//div[1]/h2") submit = (By.NAME,"btnLogin") #Action def __init__(self,driver): self.driver = driver def SetUsername(self, name): self.driver.find_element(*self.user).send_keys(name) def SetPassword(self,password): self.driver.find_element(*self.password).send_keys(password) def ClickLogin(self): self.driver.find_element(*self.submit).click() def GetLoginTitle(self): return self.driver.find_element(*self.homeText).text #Interface def TestLogin(self, username, password): self.SetUsername(username) self.SetPassword(password) self.ClickLogin()
该文件最主要的是TestLogin函数,把测试用到的数据参数化,提供给测试用例,而之前的Action是对TestLogin的进一步分层,单位动作
page_home.py
#!/usr/bin/env pythonfrom selenium import webdriverfrom selenium.webdriver.common.by import Byclass Guru99HomePage(object): HomeText_loc = (By.XPATH,"//table[1]/tbody/tr[3]/td") def __init__(self,driver): self.driver = driver def GetHomePageUserName(self): return self.driver.find_element(*self.HomeText_loc).text
该文件是成登录成功判断用的,由于在另一个页面,我们也把它作为page对象封装起来,它的接口就是GetHomePageUserName()
pom_testcase.py
#!/usr/bin/env pythonfrom selenium import webdriverfrom selenium.webdriver.support.ui import WebDriverWaitfrom selenium.webdriver.common.by import Byimport unittest, time, reimport page_homeimport page_loginclass Test_Login(unittest.TestCase): def setUp(self): self.driver = webdriver.Firefox() self.driver.implicitly_wait(10) self.driver.get("http://demo.guru99.com/v4/") def test_home_page_appear(self): objLogin = page_login.Guru99Login(self.driver) loginTitle = objLogin.GetLoginTitle() assert loginTitle == "Guru99 Bank", "title is wrong" objLogin.TestLogin("mngr44067","etUtamE") objHomePage = page_home.Guru99HomePage(self.driver) assert objHomePage.GetHomePageUserName() == "Manger Id : mngr44067", "invalid user" def tearDown(self): self.driver.close()if __name__ == '__main__': unittest.main()
测试用例用unittest
测试方法 test_home_page_appear()判断title登录判断登录成功
无论UI如何变,该测试用例无需修改,只需要修改page_login, page_home就行了,代码可用性很高,只需要改用户名,密码就能进行测试
参考:
www.guru99.comselenium guide