selenium- PO模式
1|0一、思想:
PO模式:
PageObject,从最初自动化是基于QTP来实现的,通过录制的形式,自动生成脚本,通过定义对象库来实现对页面的元素的收集,升级到关键字驱动的形式来实现自动化(通过封装对元素的操作,来实现关键字驱动),再升级到PageObject,将系统以页面来进行区分,针对不同的页面,基于页面的元素及当前页面所实现的业务,将其定义为一个完整的页面对象。然后对这个页面对象进行操作。在PO中,通过分层的形式,来定义出不同页面的操作内容:
1、BasePage:基础层,用于提供最为底层的功能,让其他页面对象可以直接进行继承
2、Page:页面层,用于提供元素的获取,各个元素的操作方法的封装
3、业务层:通过这一层的调用,传入参数,进行自动化的运行
优点:
1、针对于指定的被测业务系统的流程,执行自动化时非常简便
缺点:
1、对于多个系统的复用性相对较差
2|0二、PO实现实例
下面,以安居客登录为例
2|12.1 定义公用功能部分 basepage.py
# -*- coding:utf-8 -*-
from public.common.log import Logger
from config import globalparam
from selenium.common.exceptions import NoSuchElementException
import os
import time
logger = Logger(logger='BasePage').getlog()
class BasePage:
"""测试基类"""
def __init__(self, driver):
self.driver = driver
@staticmethod
def isdisplayed(element):
"""元素是否存在"""
value = element.is_displayed()
return value
@staticmethod
def sleep(secondes):
"""强制等待"""
time.sleep(secondes)
logger.info('Sleep for %d seconds' % secondes)
def open_url(self,url):
self.driver.get(url)
def forward(self):
"""浏览器前进"""
self.driver.forward()
logger.info("Click forward on current page.")
def back(self):
"""浏览器后退"""
self.driver.back()
logger.info("Click back on current page.")
def wait(self,seconds):
"""隐式等待"""
self.driver.implicitly_wait(seconds)
logger.info("wait for %d seconds." % seconds)
def close(self):
"""关闭当前窗口"""
try:
self.driver.close()
logger.info("Closing and quit the browser.")
except NameError as e:
logger.info("Faile to quit the browser with %s" %e)
def get_img(self):
"""截图"""
rq = time.strftime('%Y%m%d%H%M%S', time.localtime(time.time()))
screen_name = os.path.join(globalparam.test_img_path,'%s.png' % rq)
# noinspection PyBroadException
try:
self.driver.get_screenshot_as_file(screen_name)
logger.info("Had take screenshot and save to folder : /screenshots")
except NameError as e:
logger.error("Failed to take screenshot! %s" % e)
self.get_img()
def find_element(self, selector):
"""定位元素"""
by = selector[0]
value = selector[1]
element = None
if by in ['id', 'name', 'class', 'tag', 'link', 'plink', 'css', 'xpath']:
# noinspection PyBroadException
try:
if by == 'id':
element = self.driver.find_element_by_id(value)
elif by == 'name':
element = self.driver.find_element_by_name(value)
elif by == 'class':
element = self.driver.find_element_by_class_name(value)
elif by == 'tag':
element = self.driver.find_element_by_tag_name(value)
elif by == 'link':
element = self.driver.find_element_by_link_text(value)
elif by == 'plink':
element = self.driver.find_element_by_partial_link_text(value)
elif by == 'css':
element = self.driver.find_element_by_css_selector(value)
elif by == 'xpath':
element = self.driver.find_element_by_xpath(value)
else:
logger.error('Not find the element')
logger.info("Had find the element! ,by %s via value :%s " %(by,value))
# logger.info('元素定位成功。定位方式:%s,使用的值%s:' % (by, value))
return element
except NoSuchElementException as e:
logger.error("NoSuchElementException %s " %e)
self.get_img() # 调用截图
else:
logger.error('Please enter a valid type of targeting elements')
def type(self, selector, value):
"""输入内容"""
element = self.find_element(selector)
# element.clear()
logger.info('clear input_box')
# noinspection PyBroadException
try:
element.send_keys(value)
logger.info('input is:%s' % value)
except BaseException:
logger.error('Failed to type in input box', exc_info=1)
self.get_img()
#输入并确认
def type_enter(self,selector,value):
try:
element = self.find_element(selector)
element.send_keys(value)
time.sleep(1)
element.send_keys(Keys.ENTER)
except Exception as e:
logger.info("Failed to type_and_enter with %s" % e)
self.get_img()
raise
def click(self, selector):
"""点击元素"""
element = self.find_element(selector)
# noinspection PyBroadException
try:
element.click()
logger.info('"The element \' %s \' was clicked." % element.text')
except BaseException:
display = self.isdisplayed(element)
if display is True:
self.sleep(3)
element.click()
logger.info('The element was clicked')
else:
self.get_img()
logger.error('Failed to click the element', exc_info=1)
def right_click(self,selector):
"""右击元素"""
element = self.find_element(selector)
try:
ActionChains(self.driver).context_click(element).perform()
logger.info("The element \' %s \' was clicked." % element.text)
except NameError as e:
logger.error("Failed to right_click the element with %s" % e)
self.get_img()
def double_click(self,selector):
"""双击"""
element = self.find_element(selector)
try:
ActionChains(self.driver).double_click(element).perform()
except Exception as e:
logger.info("Failed to double_click the element with %s" % e)
self.get_img()
raise
def move_to_element(self,selector):
"""鼠标移到元素上"""
try:
element = self.find_element(selector)
ActionChains(self.driver).move_to_element(element).perform()
except Exception as e:
logger.info("Failed to move_to_element the element with %s" % e)
self.get_img()
raise
def drag_and_drop(self, element_selector,ta_selector):
"""拖拽"""
try:
element_drag = self.find_element(element_selector)
taget_drop = self.find_element(ta_selector)
ActionChains(self.driver).drag_and_drop(element_drag,taget_drop).perform()
except Exception as e:
logger.info("Failed to drag_and_drop the element with %s" % e)
self.get_img()
raise
def refresh(self):
"""刷新"""
self.driver.refresh()
def submit(self,selector):
"""submit"""
try:
element = self.find_element(selector)
element.submit()
except Exception as e:
logger.info("Failed to submit the element with %s" % e)
self.get_img()
def get_attribute(self,selector,attribute):
"""获取元素属性"""
try:
element = self.find_element(selector)
return element.get_attribute(attribute)
except Exception as e:
logger.info("Failed to get_attribute with %s" % e)
self.get_img()
raise
def get_text(self,selector):
"""获取元素的文本信息"""
try:
return self.find_element(selector).text
except Exception as e:
logger.info("Failed to get_text with %s" % e)
self.get_img()
def dismiss_alert(self):
"""弹窗 alert——取消"""
self.driver.switch_to.alert.dismiss()
def clear(self,selector):
"""清除文本框"""
element = self.find_element(selector)
try:
element.clear()
logger.info("Clear text in input box before typing.")
except NameError as e:
logger.error("Failed to clear in input box with %s" % e)
self.get_img()
def use_js(self, js):
"""调用js"""
# noinspection PyBroadException
try:
self.driver.execute_script(js)
logger.info('successful,js contents is:%s' % js)
except BaseException:
logger.error('js error', exc_info=1)
def switch_menue(self, parentelement, secelement, targetelement):
"""三级菜单切换"""
self.sleep(3)
# noinspection PyBroadException
try:
self.driver.switch_to_default_content()
self.click(parentelement)
logger.info('成功点击一级菜单:%s' % parentelement)
self.click(secelement)
logger.info('成功点击二级菜单:%s' % secelement)
self.click(targetelement)
logger.info('成功点击三级菜单:%s' % targetelement)
except BaseException:
logger.error('切换菜单报错', exc_info=1)
def switch_ifarme(self, selector):
"""切换ifarme"""
element = self.find_element(selector)
# noinspection PyBroadException
try:
self.driver.switch_to.frame(element)
logger.info('Successful to switch_to_frame! ')
except BaseException:
logger.error('Failed to switch_to_frame', exc_info=1)
def quit_iframe(self):
"""退出当前iframe"""
self.driver.switch_to_default_content()
def get_title(self):
"""获取title"""
title = self.driver.title
logger.info('Current page title is:%s' % title)
return title
def quit(self):
"""关闭浏览器"""
self.driver.quit()
logger.info('quit the browser')
2|22.2 页面封装 login.py
每个操作封装成一个个小组件.
这里需要注意的是
self.findElement(*self.pwtab_loc).click()
参数中,带*号,为什么要带星号,因为我们参数是一个元组.中间有By.ID这样的对像,如果不加会有问题.
#coding:utf-8
from selenium.webdriver.common.by import By
from selenium import webdriver
class LoginPage(BasePage):
#定位元素
username_loc = (By.ID,"pwdUserNameIpt")
password_loc = (By.ID,"pwdIpt")
pwtab_loc = (By.ID,"pwdTab")
btn_loc = (By.ID,"pwdSubmitBtn")
switchFrame = 0
#打开页面
def open_url(self):
self.page_open(self.base_url,self.page_title)
#切换frame
def switch_to_f(self):
self.switch_to_frame(self.switchFrame)
#切换登录方式
def switch_login(self):
self.findElement(*self.pwtab_loc).click()
#输入用户名
def inputUserName(self,username):
self.findElement(*self.username_loc).send_keys(username)
#输入pndc
def inputPassWord(self,password):
self.findElement(*self.password_loc).send_keys(password)
#单击登录按钮
def clickLogin(self):
self.findElement(*self.btn_loc).click()
if __name__=="__main__":
driver = webdriver.Firefox()
driver.implicitly_wait(30)
url = 'https://login.anjuke.com/login/form?history=aHR0cHM6Ly9zaGFuZ2hhaS5hbmp1a2UuY29tLw=='
username ='123'
password=''
Login_page = LoginPage(url,driver,u'登录')
Login_page.open_url()
Login_page.switch_to_f()
Login_page.switch_login()
Login_page.inputUserName(username)
Login_page.inputPassWord(password)
Login_page.clickLogin()
2|32.3 pytest 用例封装
__EOF__

本文作者:😎
本文链接:https://www.cnblogs.com/dongye95/p/14447495.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
本文链接:https://www.cnblogs.com/dongye95/p/14447495.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
2019-02-25 python——操作系统的发展史