-
2023年11月12日发(作者:)
selenium⾃动化测试框架PO设计模式
整理⼀下 selenium ⾃动化测试实践中使⽤较多的 PO(PageObject)设计模式
⾯向对象的特性:封装继承多态.在⾃动化中⼀样适⽤,selenium ⾃动化测试中有⼀个名字常常被提及 PageObject(思想与⾯向对象的特性
相同),通过 PO 模式可以⼤⼤提⾼测试⽤例的维护效率
传统测试脚本的弊端:
from import By
class loginPageLocator:
# ⽤户名输⼊框
user_input = (,'//input[@name="username"]')
# 密码输⼊框
passwd_input = (,'//input[@name="password"]')
# 登录按钮
login_button = (,'//button[@class="el-button el-button--primary"]')
# 错误提⽰ - 登录表单区域
form_error_info = (,'//div[@class="el-form-item__error"]')
# 登录页弹框 - 标题
login_box_title = (,'//span[text()="确定登出"]')
# 登录页弹框 - ⽂本
login_box_text = (,'//p[text()="你已被登出,可以取消继续留在该页⾯,或者重新登录"]')
# 登录页弹框 - 重新登录
login_box_relog = (,'//button[@class="el-button el-button--default el-button--small el-button--primary "]')
# 登录页弹框 - 取消
login_box_cancel = (,'//button[@class="el-button el-button--default el-button--small"]')
# 登录页弹框 - 关闭
login_box_close = (,'//i[@class="el-message-box__close el-icon-close"]')
2.页⾯元素(⾸页)
from import By
class indexPageLocator:
# 右上⾓⽤户名
user_link = (,'//li[@class="logout"]')
3.关键字封装(基础操作)
"""
1.⽣成执⾏⽇志;测试⽤例的执⾏⽇志
2.测试⽤例的任何⼀⾏代码失败,都希望能在⽇志当中看到异常信息,并且⽣成失败的⽹页截图
3.精简⼀下我的 pageobjects 页⾯
测试⽤例 = 页⾯对象(步骤+断⾔) + 测试数据
页⾯对象 = 页⾯⾏为 + 页⾯元素定位
页⾯⾏为 = selenium webdrive基本 API{查找元素等待点击输⼊清除⽂本获取属性获取}组合起来的
对 WebDrive 的基础函数封装⼀下.加⼊⽇志异常处理失败截图
BasePage 具备以上三点
"""
from import WebDriverWait
from t import expected_conditions as EC
import logging,time,datetime
from Common import file_path
from gging import MyLog
class basePage:
def __init__(self,driver):
= driver
# 等待元素可见
def wait_eleVisible(self,loc,timeout=20,poll_frequency=0.5,model=None):
"""
:param loc:元素定位表达;元组类型,表达⽅式(元素定位类型,元素定位⽅法)
:param loc:元素定位表达;元组类型,表达⽅式(元素定位类型,元素定位⽅法)
:param timeout:等待的上限
:param poll_frequency:轮询频率
:param model:等待失败时,截图操作,图⽚⽂件中需要表达的功能标注
:return:None
"""
('{} 等待元素可见:{}'.format(model,loc))
try:
start = ()
WebDriverWait(,timeout,poll_frequency).until(lity_of_element_located(loc))
end = ()
MyLog().logger().info('等待时长:%.2f 秒'%(end - start))
except:
MyLog().logger().exception('{} 等待元素可见失败:{}'.format(model,loc))
# 截图
_webImgs(model)
raise
# 等待元素不可见
def wait_eleNoVisible(self,loc,timeout=20,poll_frequency=0.5,model=None):
"""
:param loc:元素定位表达;元组类型,表达⽅式(元素定位类型,元素定位⽅法)
:param timeout:等待的上限
:param poll_frequency:轮询频率
:param model:等待失败时,截图操作,图⽚⽂件中需要表达的功能标注
:return:None
"""
('{} 等待元素不可见:{}'.format(model,loc))
try:
start = ()
WebDriverWait(,timeout,poll_frequency).until_not(lity_of_element_located(loc))
end = ()
MyLog().logger().info('等待时长:%.2f 秒'%(end - start))
except:
MyLog().logger().exception('{} 等待元素不可见失败:{}'.format(model,loc))
# 截图
_webImgs(model)
# 输⼊操作
MyLog().logger().info('{} 在元素 {} 中输⼊⽂本: {}'.format(model,loc,text))
try:
_keys(text)
except:
MyLog().logger().exception('输⼊操作失败')
# 截图
_webImgs(model)
raise
# 清除操作
def clean_Input_Text(self,loc,model=None):
ele = _Element(loc,model)
# 清除操作
MyLog().logger().info('{} 在元素 {} 中清除'.format(model,loc))
try:
()
except:
MyLog().logger().exception('清除操作失败')
# 截图
_webImgs(model)
raise
# 点击操作
def click_Element(self,loc,model=None):
# 先查找元素在点击
_webImgs(model)
raise
# iframe 切换
def switch_iframe(self,frame_refer,timeout=20,poll_frequency=0.5,model=None):
# 等待 iframe 存在
MyLog().logger().info('iframe 切换操作:')
try:
# 切换 == indexnameidWebElement
WebDriverWait(,timeout,poll_frequency).until(_to_be_available_and_switch_to_it(frame_refer))
(0.5)
MyLog().logger().info('切换成功')
except:
MyLog().logger().exception('iframe 切换失败')
# 截图
_webImgs(model)
raise
# 窗⼝切换 = 如果是切换到新窗⼝,new. 如果是回到默认的窗⼝,default
def switch_window(self,name,cur_handles=None,timeout=20,poll_frequency=0.5,model=None):
"""
调⽤之前要获取window_handles
:param name: new 代表最新打开的⼀个窗⼝. default 代表第⼀个窗⼝. 其他的值表⽰为窗⼝的 handles
:param cur_handles:
:param timeout:等待的上限
:param poll_frequency:轮询频率
:param model:等待失败时,截图操作,图⽚⽂件中需要表达的功能标注
:return:
"""
try:
if name == 'new':
if cur_handles is not None:
MyLog().logger().info('切换到最新打开的窗⼝')
WebDriverWait(,timeout,poll_frequency).until(_window_is_opened(cur_handles))
window_handles = _handles
_(window_handles[-1])
else:
MyLog().logger().exception('切换失败,没有要切换窗⼝的信息')
_webImgs(model)
raise
elif name == 'default':
MyLog().logger().info('切换到默认页⾯')
_t()
else:
MyLog().logger().info('切换到为 handles 的窗⼝')
_(name)
except:
MyLog().logger().exception('切换窗⼝失败')
# 截图
_webImgs(model)
raise
# 截图
def save_webImgs(self,model=None):
# filepath = 指图⽚保存⽬录/model(页⾯功能名称)_当前时间到秒.png
4.页⾯操作脚本
from age_locator import loginPageLocator as loc
from ge import basePage
class LoginPage(basePage):
# 登录操作
def login(self,username,passwd):
# 等待⽤户名⽂本框元素出现
_eleVisible(_input,model='等待⽤户名⽂本框元素出现')
# 清除⽂本框内容
_Input_Text(_input,model='清除⽤户名⽂本框内容')
# 输⼊⽤户名
_Text(_input,text=username,model='输⼊⽤户名')
# 等待密码⽂本框元素出现
_eleVisible(_input,model='等待密码⽂本框元素出现')
# 清除密码⽂本框内容
_Input_Text(_input,model='清除密码⽂本框内容')
# 输⼊密码
_Text(_input,text=passwd,model='输⼊密码')
# 点击登录按钮
_Element(_button,model='点击登录按钮')
# 获取页⾯错误提⽰ - 登录表单区域
def get_wrongMsg_byForm(self):
# 等待表单⽂本提⽰元素出现
_eleVisible(_error_info,model='等待表单⽂本提⽰元素出现')
return _Text(_error_info,model='获取表单⽂本提⽰内容')
def get_boxMsg(self):
# 等待提⽰弹框出现
_eleVisible(_box_text,model='等待提⽰弹框⽂本内容')
return _Text(_box_text,model='获取提⽰框⽂本内容')
将上⾯的脚本放在 login_ 中
5.因为是测试登录,所以写个登录成功跳转到⾸页获取其中⼀个标志元素
# 正常场景 - 登录成功
login_success_data = {"user":"test","passwd":"123456"}
# 异常场景 - ⽤户名为空⽤户名密码为空密码为空
wrong_data = [
{"user":"","passwd":"123456","check":"请输⼊⼤于5位的⽤户名"},
{"user":"","passwd":"","check":"请输⼊⼤于5位的⽤户名"},
{"user":"test","passwd":"","check":"密码不能⼩于5位"}
]
# 异常场景 - 错误的⽤户名错误的密码
error_userOrPasswd = [
{"user":"tes","passwd":"123456","check":"你已被登出,可以取消继续留在该页⾯,或者重新登录"},
{"user":"test","passwd":"1234567","check":"你已被登出,可以取消继续留在该页⾯,或者重新登录"}
]
8.编写测试⽤例:
import unittest
from selenium import webdriver
from _page import LoginPage
from _page import IndexPage
from testDatas import common_datas as cd
from testDatas import login_datas as ld
from ddt import ddt,data
@ddt
class TestLogin(se):
def setUp(self):
# 打开浏览器,访问登录页⾯
= ()
ze_window()
(_url)
= LoginPage()
def tearDown(self):
()
# 正常场景:登录成功
def test_login_success(self):
# 步骤 测试数据:sporttest/123456
# 登录页⾯ - 登录功能 - 输⼊⽤户名和密码
(_success_data['user'],_success_data['passwd'])
# 断⾔
True(IndexPage().is_user_link_exists())
-
更多推荐
设计公司
发布评论