POM是什么
- 页面对象模型(POM)是一种设计模式,用来管理维护一组web元素集的对象库。
- 在POM下,应用程序的每一个页面都有一个对应的page class
- 每一个page class维护着该web页的元素集和操作这些元素的方法
- page class中的方法命名最好根据其对应的业务场景进行
- 例如通常登录后我们需要等待几秒中,我们可以这样命名该方法:waitingForLoginSuccess()。
POM的优势
- POM提供了一种在UI层操作、业务流程与验证分离的模式,这使得测试代码变得更加清晰和高可读性。
- 对象库与用例分离,使得我们更好的复用对象,甚至能与不同的工具进行深度结合应用。
- 可复用的页面方法代码会变得更加优化。
- 更加有效的命名方式使得我们更加清晰的知道方法所操作的UI元素。
POM应用
- Page基类
- 基础操作
- 各个网页类
- 继承Page基类
- 实现各自网页里的具体操作
Page基类
- 新建pagebase包、webpage.py模块。
- 设计Page基类:Page基类,所有page都应该继承该类。
from selenium.common.exceptions import NoSuchElementException
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
class WebPage:
# 设计Page基类构造方法:初始化driver、base_url、timeout、wait等属性。
def __init__(self, driver, base_url=u"http://192.168.58.134:8080/integration/manage"):
self.driver = driver
self.base_url = base_url
self.timeout = 15
self.wait=WebDriverWait(driver,self.timeout)
# 查找元素和获得文本
def find_element(self, loc):
return self.driver.find_element(*loc)
def get_text(self,loc):
return self.find_element(loc).text
# 判断元素是否出现
def is_element_present(self,loc):
"""判断元素是否出现"""
try:
self.find_element(loc)
except NoSuchElementException:
return False
return True
# 输入和点击操作:清空后输入、点击
def input_text(self, loc, text):#清空后输入
ele=self.find_element(loc)
ele.clear()
ele.send_keys(text)
#点击
def click(self, loc):
self.find_element(loc).click()
# 切换frame和等待出现、等待消失
def switch_frame(self,frame_loc):#切换frame
self.wait.until(EC.frame_to_be_available_and_switch_to_it(frame_loc))
def wait_for_presence(self,loc):#等待出现
self.wait.until(EC.presence_of_element_located(loc))
def wait_for_disappear(self,loc):等待消失
self.wait.until_not(EC.presence_of_element_located(loc))
# 滚动条操作:滚动到底部、滚动到顶部
def to_bottom(self):
js = 'window.scrollTo(0, document.body.scrollHeight);'
self.driver.execute_script(js)# 滚动条滑动到底部
def to_top(self):
js2 = "window.scrollTo(document.body.scrollHeight, 0);"
self.driver.execute_script(js2) # 滚动条滑动到顶部
# 移动光标到元素上
def move_to_element(self,loc):#移动光标到元素上
e=self.find_element(loc)
ActionChains(self.driver).move_to_element(e).perform()
登录页和主页
后台登录页
- 打开后台登录页
- 后台登录
- 包:page
- 模块:后台_登录_page_v1.py
- 类:BgLoginPage
打开后台登录页
- 新建page包:后台_登录_page_v1.py
from pagebase.webpage import WebPage
from selenium.webdriver.common.by import By
class BgLoginPage(WebPage):
def open(self):#打开该网页
self.driver.get(self.base_url)
# 后台登录
def login(self,un,pw):
self.input_text((By.ID, "userName"),un)
self.input_text((By.ID, "password"),pw)
self.click((By.XPATH, "//span[text()='登录']"))
后台主页
- 退出
- 展开基础设置
- 等待基础设置被打开
- 进入赛区管理
- 切换到赛区管理子网页
- 包:page
- 模块:后台_主页_page_v1.py
- 类:BgHomePage
page包:后台_主页_page_v1
from selenium.webdriver.common.by import By
from pagebase.webpage import WebPage
class BgHomePage(WebPage):
def logout(self):
self.click((By.CLASS_NAME, "退出"))
# 赛区管理相关
def open_basic_setting(self):#展开基础设置
self.click((By.ID, "213"))
def wait_basic_setting_opened(self):#等待基础设置被打开
self.wait_for_presence((By.XPATH, "//div[@id='213']/img[@class='open']"))
def to_division_manager(self):# 进入赛区管理
self.click((By.ID, "214"))
def switch_to_division_manager_frame(self):#切换到赛区管理子网页
self.switch_frame((By.XPATH,"//iframe[@data-itemid='213']"))
改造根目录下conftest.py
from page.后台_登录_page_v1 import BgLoginPage#新增
# 修改打开网站后台登录页的代码
# driver.get("http://192.168.58.134:8080/integration/manage")#修改前
BgLoginPage(driver).open()#修改后
yield driver
sleep(2)
driver.quit()
# driver.find_element(By.ID, "userName").clear()#修改前
# driver.find_element(By.ID, "userName").send_keys("root")#修改前
# driver.find_element(By.ID, "password").clear()#修改前
# driver.find_element(By.ID, "password").send_keys("12345678")#修改前
# driver.find_element(By.XPATH, "//span[text()='登录']").click()#修改前
BgLoginPage(driver).login("root","12345678")#修改后
# 修改从主页退出到登录页的代码
# driver.find_element(By.ID, "userName").clear()#修改前
# driver.find_element(By.ID, "userName").send_keys("root")#修改前
# driver.find_element(By.ID, "password").clear()#修改前
# driver.find_element(By.ID, "password").send_keys("12345678")#修改前
# driver.find_element(By.XPATH, "//span[text()='登录']").click()#修改前
BgLoginPage(driver).login("root","12345678")#修改后
sleep(1)
yield driver
driver.switch_to.default_content()
# driver.find_element(By.CLASS_NAME, "退出").click()#修改前
BgHomePage(driver).logout()#修改后
赛区管理页
- 用赛区名称查询
- 判断存在
- 确认删除
- 添加赛区
- 等待加载完毕
- 切换到添加赛区子网页
- 包:page
- 模块:后台_双创_基础设置_赛区管理_page_v1.py
- 类:BgDivisionManagerPage
用赛区名称查询
- page包:后台_双创_基础设置_赛区管理_page_v1.py
from selenium.webdriver.common.by import By
from pagebase.webpage import WebPage
class BgDivisionManagerPage(WebPage):
def search(self,division_name):#用赛区名称查询
self.input_text((By.ID,"_easyui_textbox_input1"),division_name)
self.click((By.XPATH,"//span[text()='查询']"))
# 判断存在和确认删除
def is_division_exist(self,division_name):
return self.is_element_present((By.XPATH,f"//td[@field='name']/div[text()='{division_name}']"))#判断查询结果里是否存在等于目标赛区名称的记录
def delete_and_confirm(self,division_name):#删除
self.click((By.XPATH,f"//td[div='{division_name}']/../td[@field='view']/div/a[2]"))
self.click((By.XPATH,"//span[text()='确定']"))
# 添加赛区相关
def to_add_division(self):#添加赛区
self.click((By.XPATH,"//span[text()='添加赛区']"))
self.wait_for_disappear(((By.ID,"Loading")))
def wait_for_loaded(self):#等待加载完毕
self.wait_for_disappear((By.ID,"Loading"))
def switch_to_add_page(self):#切换到添加赛区子网页
self.switch_frame((By.ID,"frmDlg"))
# 判断信息是否存在和等待信息消失
def is_message_exist(self,message):#判断信息是否存在
xpath1="//div[text()='赛区信息保存成功']" if message == "赛区信息保存成功" else f"//td[text()='{message}']"
return self.is_element_present((By.XPATH, xpath1))
def wait_message_dispear(self,message):#等待信息消失
xpath1="//div[text()='赛区信息保存成功']" if message == "赛区信息保存成功" else f"//td[text()='{message}']"
self.wait_for_disappear((By.XPATH, xpath1))
添加赛区页
- 输入赛区名称
- 提交
- 取消
- 等待加载完毕
- 获得浮动提示
- 包:page
- 模块:后台_双创_基础设置_添加赛区_page_v1.py
- 类:BgAddDivisionPage
输入赛区名称
from selenium.webdriver.common.by import By
from pagebase.webpage import WebPage
class BgAddDivisionPage(WebPage):
def input_division_name(self,division_name):#输入赛区名称
self.input_text((By.ID,"_easyui_textbox_input1"),division_name)
# 提交、取消
def submit(self):#提交
self.click((By.ID,"pButton_ctlSave"))
def cancel(self):#取消
self.click((By.ID,"pButton_ctlCancel"))
# 等待加载完毕、获得浮动提示
def wait_for_loaded(self):#等待加载完毕
self.wait_for_disappear((By.ID,"Loading"))
def get_tooltip(self):#获得浮动提示
self.move_to_element((By.ID,"_easyui_textbox_input1")) # 鼠标悬停在赛区名称文本框
tooltip = self.get_text((By.CLASS_NAME, "tooltip"))
return tooltip
作者:暄总-tester