Page Object专题
页面对象模型的设计优势:
图片来源:
https://www.guru99.com/page-object-model-pom-page-factory-in-selenium-ultimate-guide.html
目的:测试代码与被测页面对象代码分离,后期如果有页面元素发生了更改,只需要修改相应页面对象的代码(即对应Class文件),而不需要修改测试的代码。
尽量使用XPath来寻找页面元素。
from selenium import webdriver
2 from selenium.webdriver.firefox.firefox_binary import FirefoxBinary
3 import time
4
5 binary=FirefoxBinary('/usr/local/firefox/firefox')
6 driver=webdriver.Firefox(firefox_binary=binary)
7 print('Before login================')
8 title=driver.title
9 print(title)
10 now_url=driver.current_url
11 print(now_url)
12
13 driver.implicitly_wait(10)
14 driver.get("https://mail.qq.com/")
15 driver.switch_to_frame("login_frame")
16 driver.find_element_by_id("u").clear()
17 driver.find_element_by_id("u").send_keys("*")
18 driver.find_element_by_xpath("//*[@id='p']").clear()
19 driver.find_element_by_xpath("//*[@id='p']").send_keys("*")
20 driver.find_element_by_xpath("//*[@id='login_button']").click()
21 print('After login===================')
22 title=driver.title
23 print(title)
24 now_url=driver.current_url
25 print(now_url)
26 user=driver.find_element_by_xpath("//*[@id='useralias']").text
27 print(user)
28 driver.quit()
用PageObject改造后:page.py,element.py,locators.py,测试文件是test_qq.py
参照
的写法写了一下,执行时长11s.
test_qq.py
1 import unittest
2 from selenium import webdriver
3 from selenium.webdriver.firefox.firefox_binary import FirefoxBinary
4 import page
5 import time
6
7
8 class LoginQQ(unittest.TestCase):
9 def setUp(self):
10 binary=FirefoxBinary('/usr/local/firefox/firefox')
11 self.driver = webdriver.Firefox(firefox_binary=binary)
12 self.driver.implicitly_wait(10)
13 self.driver.get("https://mail.qq.com/")
#跳转表单,这里没有分割出来,需要改进
14 self.driver.switch_to_frame("login_frame")
15 def test_login(self):
16 main_page = page.MainPage(self.driver)
#测试数据
17 main_page.input_username="*"
18 main_page.input_password="*"
19 main_page.click_button()
20 def tearDown(self):
21 self.driver.close()
22 if __name__ == "__main__":
23 unittest.main()
page.py
1 from element import BasePageElement
2 from locators import MainPageLocators
6 class UsernameElement(BasePageElement):
7 #元素定位
locator='u'
8 class PasswordElement(BasePageElement):
9 locator='p'
10 class BasePage(object):
11 def __init__(self,driver):
12 self.driver=driver
13 class MainPage(BasePage):
14 input_username=UsernameElement()
15 input_password=PasswordElement()
16 def click_button(self):
17 element=self.driver.find_element(*MainPageLocators.login_loc)
18 element.click()
element.py
1#元素操作
2 class BasePageElement(object):
3 def __set__(self,obj,value):
4 driver=obj.driver
5 driver.find_element_by_id(self.locator).clear()
6 driver.find_element_by_id(self.locator).send_keys(value)
7
8 def __get__(self,obj,owner):
9 driver=obj.driver
10 element=driver.find_element_by_id(self.locator)
11 return element.get_attribute("value")
locators.py
1 from selenium.webdriver.common.by import By
2 class MainPageLocators(object):
3 login_loc = (By.XPATH,"//*[@id='login_button']")
又经过虫师的书以及网上一些参考,进一步优化PageObject如下。
主要思想:将一个page对象封装成一个HTML页面,然后通过提供的应用程序特定的API来操作页面元素。一个API是关于应用的,一个API是关于HTML的。因此,page对象提供一个易于编程的接口并隐藏窗口中底层的部件。
即page对象应当将GUI控件上所有查询和操作数据的行为封装为方法
test_qq.py
#coding=utf-8
2 import unittest
3
4 from po_model import LoginPage
5 from selenium import webdriver
6 from selenium.webdriver.firefox.firefox_binary import FirefoxBinary
7 from po_model import test_user_login
8 from time import sleep
9 class test_qq(unittest.TestCase):
10 def setUp(self):
11 binary=FirefoxBinary('/usr/local/firefox/firefox')
12 self.driver=webdriver.Firefox(firefox_binary=binary)
13 self.driver.implicitly_wait(30)
14 def test_login(self):
15 username='*'
16 password='*'
17 test_user_login(self.driver,username,password)
18 sleep(3)
19 text = self.driver.find_element_by_xpath("//*[@id='useraddr']").text
20 assert(text == '[email protected]',"用户名称不匹配,登录失败")
21 def tearDown(self):
22 self.driver.quit()
23 if __name__ == "__main__":
24 unittest.main()
po_model.py
#coding=utf-8
from selenium import webdriver
from selenium.webdriver.firefox.firefox_binary import FirefoxBinary
from selenium.webdriver.common.by import By
from time import sleep
class Page(object):
'''
基础类,用于页面对象类的继承
'''
login_url="https://mail.qq.com"
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)
def open(self):
self._open(self.url)
def switch(self):
return self.driver.switch_to_frame(self.framename)
def find_element(self,*loc):
return self.driver.find_element(*loc)
class LoginPage(Page):
'''
qq邮箱登录页面模型
'''
url='/'
#定位器
username_loc=(By.ID,"u")
password_loc=(By.ID,"p")
login_loc = (By.XPATH,"//*[@id='login_button']")
#Action
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 submit(self):
self.find_element(*self.login_loc).click()
def test_user_login(driver,username,password):
'''
测试获取的用户名/密码是否可以登录
'''
login_page=LoginPage(driver)
login_page.open()
driver.switch_to_frame("login_frame")
login_page.type_username(username)
login_page.type_password(password)
login_page.submit()