UI自动化之混合框架

什么是混合框架,混合框架就是将数据驱动与关键字驱动结合在一起,主要用来回归业务主流程,将核心流程串联起来。

上一篇我们写到了关键字驱动框架,关键字驱动框架是针对一个业务场景的单条测试用例的。

我们以163邮箱的登录到创建联系人这个流程为例,来看看混合框架是怎样的。

首先准备一个存放测试用例和数据的excel文件,文件内容如下:

测试用例的sheet页:case

mock表示这条测试用例我们需要用到的框架模型,key表示关键字,data表示数据

step_sheet表示这条用例我们需要用到的关键字驱动的sheet页名称

data_sheet表示这条用例我们需要用到的数据驱动的sheet页名称

login_step页:

add_person_step页:添加联系人的步骤

add_person_data页:添加联系人所需要用到的数据

excel的准备工作就完成了,接下来看代码:

首先是项目目录:只写了简单的几个目录,其他的目录在pageobject三层架构中写过,可以参考,都是一样的。

Setting文件夹的Config.py文件:

# Config.py
import osBase_Dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))# 测试数据文件
Test_Data_Path = os.path.join(Base_Dir, 'TestData')

Util文件夹的find_ele.py文件:

# find_ele.py
from selenium.webdriver.support.wait import WebDriverWaitdef find_element(driver, location_type, location_express):'''查找控件元素'''try:driver = WebDriverWait(driver, 20).until(lambda driver:driver.find_element(location_type, location_express))return driverexcept Exception as e:raise edef find_elements(driver, location_type, location_express):'''查找元素组'''try:driver = WebDriverWait(driver, 20).until(lambda driver:driver.find_elements(location_type, location_express))return driverexcept Exception as e:raise e

Util文件夹的excel_parse.py文件:读取excel的内容

# excel_parse.py
from Setting.Config import Test_Data_Path
from openpyxl import load_workbookclass ExcelParse:def __init__(self):self.workbook = None# self.sheet = Nonedef load_workbook(self, filename):'''加载文件'''try:self.workbook = load_workbook(filename)except Exception as e:raise edef get_sheet(self, sheetname):'''获取sheet页'''try:# self.sheet = self.workbook[sheetname]return self.workbook[sheetname]except Exception as e:raise edef get_row_num(self, sheet):'''返回行数'''# return self.sheet.max_rowreturn sheet.max_rowdef get_col_num(self, sheet):'''返回列数'''# return self.sheet.max_columnreturn sheet.max_columndef get_cell_value(self, sheet, row, col):'''返回某一单元格的值'''# return self.sheet.cell(row=row, column=col).valuereturn sheet.cell(row=row, column=col).valuedef get_row_value(self, sheet, row):'''返回某一行的值'''try:col = self.get_col_num(sheet)data = []for i in range(1, col+1):data.append(self.get_cell_value(sheet, row, i))return dataexcept Exception as e:raise edef write_cell(self, sheet, row, col, filename, content):'''单元格赋值'''try:# self.sheet.cell(row=row, column=col, value=content)sheet.cell(row=row, column=col, value=content)self.workbook.save(filename)except Exception as e:raise eif __name__ == '__main__':execl = ExcelParse()execl.load_workbook(Test_Data_Path + '/test_data.xlsx')sheet = execl.get_sheet('case')# execl.get_sheet('login')res = execl.get_row_value(sheet, 2)print(res)

Util文件夹的elementAction.py文件:执行动作的封装

# elementAction.py
import timefrom selenium import webdriver
from Util.find_ele import find_element, find_elementsdriver = Nonedef open_browse(browser_name, *args):'''打开浏览器'''global drivertry:if browser_name.lower() == 'chrome':driver = webdriver.Chrome()elif browser_name.lower() == 'firefox':driver = webdriver.Firefox()else:driver = webdriver.Ie()except Exception as e:raise edef get_url(url, *args):'''打开网址'''try:driver.get(url)except Exception as e:raise edef max_window(*args):'''窗口最大化'''try:driver.maximize_window()except Exception as e:raise edef switch_frame(location_type, location_express, *args):'''切换iframe'''try:frame = find_element(driver, location_type, location_express)driver.switch_to.frame(frame)except Exception as e:raise edef input_content(location_type, location_express, content, *args):'''定位输入框,输入内容'''try:find_element(driver, location_type, location_express).send_keys(content)except Exception as e:raise edef input_subject(location_type, location_express, input_conetnt, *args):'''定位输入框,输入内容'''try:# location_express的值为:location_express, index = location_express.split(',')find_elements(driver, location_type, location_express)[int(index)].send_keys(input_conetnt)except Exception as e:raise edef switch_default(*args):'''返回默认iframe'''try:driver.switch_to.default_content()except Exception as e:raise edef click(location_type, location_express, *args):'''点击操作'''try:find_element(driver, location_type, location_express).click()except Exception as e:raise edef assert_title(title, *args):'''断言title是否正确'''try:assert title in driver.titleexcept Exception as e:raise edef close_browse():'''关闭浏览器'''driver.quit()def sleep(sec):'''等待'''time.sleep(sec)if __name__ == '__main__':open_browse('chrome')get_url('http://mail.163.com')max_window()switch_frame('tag name', 'iframe')input_content('name', 'email', 'YM_yimin')input_content('name', 'password', 'yimin19960930')click('id', 'dologin')assert_title('网易')

Util文件夹的common.py文件:封装拼接的执行动作函数

# common.py
def generate_method_express(location_type, location_express, key_word, operate_data):# location_type, location_express为空,operate_data不为空if key_word and operate_data and location_type is None and location_express is None:# 判断操作值的类型if isinstance(operate_data, int):method_express = key_word + '(' + str(operate_data) + ')'else:method_express = key_word + "('" + operate_data + "')"# print(method_express)# 只有关键字有值,其他的都为空,比如:max_window, close_browseelif key_word and operate_data is None and location_type is None and location_express is None:method_express = key_word + '()'# print(method_express)# location_type,location_express不为空,operate_data为空elif key_word and location_type and location_express and operate_data is None:method_express = key_word + "('" + location_type + "','" + location_express + "')"# print(method_express)# 都不为空else:if isinstance(operate_data, int):method_express = key_word + "('" + location_type + "','" + location_express + "'," + str(operate_data) + ")"else:method_express = key_word + "('" + location_type + "','" + location_express + "','" + operate_data + "')"print(method_express)return method_express

TestScript文件夹下的add_contractor.py文件:添加联系人的测试用例执行

# 添加联系人
import timefrom Util.common import generate_method_express
from Util.excel_parse import ExcelParse
from Setting.Config import Test_Data_Path
from Util.elementAction import *
from Util import elementAction
from Util.find_ele import find_elementdef add_contractors(excel, stepSheet, dataSheet):'''添加联系人'''# 数据源行数data_row_nums = excel.get_row_num(dataSheet)# 步骤行数step_row_nums = excel.get_row_num(stepSheet)# 成功的步骤数success_record = 0# 数据驱动sheet页中需要执行的行数need_run_record = 0# 遍历数据驱动sheet页中的数据for i in range(2, data_row_nums):# 判断数据驱动sheet页的数据是否需要执行if excel.get_cell_value(dataSheet, i, 6).lower() == 'y':need_run_record += 1# 将这一行的数据全部拿出来name = excel.get_cell_value(dataSheet, i, 1)   # 姓名email = excel.get_cell_value(dataSheet, i, 2)   # 邮箱is_star = excel.get_cell_value(dataSheet, i, 3)   # 是否星标phone = excel.get_cell_value(dataSheet, i, 4)    # 电话号码remarks = excel.get_cell_value(dataSheet, i, 2)   # 备注success_step = 0     # 记录每行数据成功的步骤数# 编辑关键字驱动sheet页中的步骤for j in range(2, step_row_nums):# 获取关键字驱动sheet页中的每行数据step_desc = excel.get_cell_value(stepSheet, j, 2)         # 步骤描述location_type = excel.get_cell_value(stepSheet, j, 3)     # 定位方式location_express = excel.get_cell_value(stepSheet, j, 4)   # 定位方式表达式keyword = excel.get_cell_value(stepSheet, j, 5)           # 关键字operate_value = excel.get_cell_value(stepSheet, j, 6)      # 操作值# 当操作值是变量的时候,要引用数据源(数据驱动sheet页)中的数据# operate_value的值是字符串,并且以${开头,}结尾, 例如operate_value='${name}'if isinstance(operate_value, str) and operate_value.startswith('${') and operate_value.endswith('}'):# 把operate_value中的变量名截取出来operate_value = eval(operate_value[2:operate_value.index('}')])# 组装函数,拼接每个步骤的执行动作函数func_express = generate_method_express(location_type, location_express, keyword, operate_value)# 当step_desc为星标是否选择时,当operate_value等于Y(即执行点击操作),选中星标,当operate_value等于Y,不选中星标(即不执行点击操作)# func_express = click(location_type, location_express, 'Y/N')if operate_value != 'no_star':# 执行选中星标,点击操作try:eval(func_express)except Exception as e:raise eelse:# 执行选中星标操作,没有异常,成功步骤+1success_step += 1else:# 不执行选中星标操作,要记录成功步骤数success_step += 1# 判断成功步骤数,与关键字驱动sheet页的步骤数是否相等if success_step+1 == step_row_nums:# 成功步骤数+1 等于 关键字驱动sheet页的行数, 成功的数据+1success_record += 1# 将成功的结果写入数据驱动sheet页对应的单元格excel.write_cell(dataSheet, i, 7, Test_Data_Path+'/test_data.xlsx', 'pass')else:excel.write_cell(dataSheet, i, 7, Test_Data_Path + '/test_data.xlsx', 'fail')# 数据驱动sheet页中的所有数据全部轮训执行完之后# 判断成功记录数success_record 和 需要执行的数据need_run_record  相等,则说明该测试用例执行成功if success_record == need_run_record:return 'Pass'else:return 'Fail'if __name__ == '__main__':from selenium import webdriverdriver = webdriver.Chrome()driver.get('http://mail.163.com')frame = find_element(driver, 'tag name', 'iframe')driver.switch_to.frame(frame)find_element(driver, 'name', 'email').send_keys('test123')find_element(driver, 'name', 'password').send_keys('a123456')find_element(driver, 'id', 'dologin').click()time.sleep(5)elementAction.driver = driverexecl = ExcelParse()execl.load_workbook(Test_Data_Path + '/test_data.xlsx')step_sheet = execl.get_sheet('add_person_step')data_sheet = execl.get_sheet('add_person_data')add_contractors(execl,step_sheet, data_sheet)

TestScript文件夹的test_login_add_send.py文件:读取case页的测试用例,进行执行

# test_login_add_send.py
from Util.excel_parse import ExcelParse
from Setting.Config import Test_Data_Path
from TestScript.add_contractor import add_contractors
from Util.common import generate_method_expressdef test_loginAndAddAndSend():try:# 获取数据文件case中的内容excel = ExcelParse()excel.load_workbook(Test_Data_Path + '/test_data.xlsx')case_sheet = excel.get_sheet('case')    # 获取测试用例sheet页case_nums = excel.get_row_num(case_sheet)     # case的总行数# 遍历case中的数据for i in range(2, case_nums+1):# 判断该用例是否要执行if excel.get_cell_value(case_sheet, i, 7) == 'y':# 获取用例名称case_name = excel.get_cell_value(case_sheet, i, 2)# 框架类型frame_mode = excel.get_cell_value(case_sheet, i, 4)# 步骤sheet名step_sheet_name = excel.get_cell_value(case_sheet, i, 5)stepsheet = excel.get_sheet(step_sheet_name)   # 获取步骤sheet页if frame_mode == 'data':# 如果框架类型为data,获取数据sheet名data_sheet_name = excel.get_cell_value(case_sheet, i, 6)# 分别获取两个sheet,作为参数传入datasheet = excel.get_sheet(data_sheet_name)result = None# 调用对应的方法,即添加联系人的方法if case_name == 'add_person':result = add_contractors(excel, stepsheet, datasheet)if result == 'Pass':excel.write_cell(case_sheet, i, 8, Test_Data_Path + '/test_data.xlsx', 'Pass')else:excel.write_cell(case_sheet, i, 8, Test_Data_Path + '/test_data.xlsx', 'Fail')elif frame_mode == 'key':# 获取步骤数step_nums = excel.get_row_num(stepsheet)# 记录成功的步骤数success_step_num = 0for j in range(2, step_nums+1):# 步骤描述step_desc = excel.get_cell_value(stepsheet, j, 2)location_type = step_desc = excel.get_cell_value(stepsheet, j, 3)location_express = step_desc = excel.get_cell_value(stepsheet, j, 4)key_word = excel.get_cell_value(stepsheet, j, 5)operate_value = step_desc = excel.get_cell_value(stepsheet, j, 6)# 构建函数表达式func_express = generate_method_express(location_type, location_express, key_word, operate_value)# 执行函数, 不抛出异常就认为执行成功try:print(f'开始执行 {step_desc}')eval(func_express)except Exception as e:print(f'执行{step_desc}发生异常{e}')# 某一步发生异常,则该用例执行失败,将失败结果写入测试用例(case)sheet页excel.write_cell(case_sheet, i, 8, Test_Data_Path + '/test_data.xlsx', 'Fail')else:success_step_num += 1# 执行成功步骤数+1 = 步骤总数,用例执行成功if success_step_num+1 == step_nums:# 写入成功excel.write_cell(case_sheet, i, 8, Test_Data_Path + '/test_data.xlsx', 'Pass')else:excel.write_cell(case_sheet, i, 8, Test_Data_Path + '/test_data.xlsx', 'Skip')except Exception as e:raise e

最后执行test_login_add_send.py文件,即实现了混合框架。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/124163.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

云计算中的负载均衡技术,确保资源的平衡分配

文章目录 1. 硬件负载均衡器2. 软件负载均衡器3. DNS负载均衡4. 内容分发网络(CDN) 🎈个人主页:程序员 小侯 🎐CSDN新晋作者 🎉欢迎 👍点赞✍评论⭐收藏 ✨收录专栏:云计算 ✨文章内…

【负载均衡】常见的负载均衡策略有哪些?

文章目录 前言负载均衡分类常见负载均衡策略小结 前言 负载均衡策略是实现负载均衡器的关键,而负载均衡器又是分布式系统中不可或缺的重要组件。使用它有助于提高系统的整体性能、可用性、可靠性和安全性,同时支持系统的扩展和故障容忍性。对于处理大量…

el-form表单动态校验(场景: 输入框根据单选项来动态校验表单 没有选中的选项就不用校验)

el-form表单动态校验 el-form常规校验方式: // 结构部分 <el-form ref"form" :model"form" :rules"rules"><el-form-item label"活动名称: " prop"name" required><el-input v-model"form.name" /…

面试中的时间管理:如何在有限时间内展示最大价值

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…

客户端发现pod并与之通信

客户端发现pod并与之通信 pod需要一种寻找其他pod的方法来使用其他pod提供的服务&#xff0c;不像在没有Kubernetes的世界&#xff0c;系统管理员要在用户端配置文件中明确指出服务的精确IP地址 或者主机名来配置每个客户端应用&#xff0c;但同样的方法在Kubernetes中不适用 …

IIS WebDAV配置,https绑定及asp设置

IIS支持标准CGI&#xff0c;因此可以用程序语言针对STDIN和STDOUT开发。 IIS CGI配置和CGI程序FreeBasic, VB6, VC 简单样例_Mongnewer的博客-CSDN博客 IIS支持脚本解释CGI&#xff0c;因此可以用脚本语言针对STDIN和STDOUT开发。 IIS perl python cbrother php脚本语言配置…

(二十三)大数据实战——Flume数据采集之采集数据聚合案例实战

前言 本节内容我们主要介绍一下Flume数据采集过程中&#xff0c;如何把多个数据采集点的数据聚合到一个地方供分析使用。我们使用hadoop101服务器采集nc数据&#xff0c;hadoop102采集文件数据&#xff0c;将hadoop101和hadoop102服务器采集的数据聚合到hadoop103服务器输出到…

3dMax全球学习资源、资源文件和教程 !

此样例教育教程和学习资源旨在提供使用Autodesk 3ds Max时的计划知识和培训、正确的工作流、流程管理和最佳实践。 您在Autodesk三维设计领域的职业生涯 有关使用3ds Max和Maya在计算机图形领域开始职业生涯的提示&#xff08;包括新的3ds Max和Maya介绍教程&#xff0c;以复…

vmware fusion12共享文件夹到虚拟机window10

文章目录 一、window10虚拟机安装VMware Tools二、MAC配置共享文件夹三、使用 一、window10虚拟机安装VMware Tools vmware fusion—虚拟机----安装VMware Tools–一路下一步 确认安装 双击进行安装 一路下一步&#xff0c;傻瓜式安装 二、MAC配置共享文件夹 设置—系…

浅谈Spring

Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器&#xff08;框架&#xff09;。 一、什么是IOC&#xff1f; IoC Inversion of Control 翻译成中⽂是“控制反转”的意思&#xff0c;也就是说 Spring 是⼀个“控制反转”的容器。 1.1控制反转推导 这个控制反转怎…

类的加载过程

清楚每个环节的操作过程就可以了 1.加载Loading 加载过程&#xff1a; 通过一个类的全限定名获取定义此类的二进制字节流将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构在内存中生成一个代表这个类的java.lang.class对象&#xff0c;作为方法区这个类的各种数…

Gitea--私有git服务器搭建详细教程

一.官方文档 https://docs.gitea.com/zh-cn/说明 gitea 是一个自己托管的Git服务程序。他和GitHub, Gitlab等比较类似。他是从 Gogs 发展而来&#xff0c;gitea的创作团队重新fork了代码&#xff0c;并命名为giteagitea 功能特性多&#xff0c;能够满足我们所有的的代码管理需…

nowcoder NC10 大数乘法

题目链接&#xff1a; https://www.nowcoder.com/practice/c4c488d4d40d4c4e9824c3650f7d5571?tpId196&tqId37177&rp1&ru/exam/company&qru/exam/company&sourceUrl%2Fexam%2Fcompany&difficultyundefined&judgeStatusundefined&tags&tit…

《异常检测——从经典算法到深度学习》22 Kontrast: 通过自监督对比学习识别软件变更中的错误

《异常检测——从经典算法到深度学习》 0 概论1 基于隔离森林的异常检测算法 2 基于LOF的异常检测算法3 基于One-Class SVM的异常检测算法4 基于高斯概率密度异常检测算法5 Opprentice——异常检测经典算法最终篇6 基于重构概率的 VAE 异常检测7 基于条件VAE异常检测8 Donut: …

Unity中Shader的屏幕坐标

文章目录 前言一、屏幕坐标1、屏幕像素的坐标2、屏幕坐标归一化 二、在Unity中获取 当前屏幕像素 和 总像素1、获取屏幕总像素,使用_ScreenParams参数2、获取当前片段上的像素怎么使用:在片元着色器传入参数时使用 前言 Unity中Shader的屏幕坐标 一、屏幕坐标 1、屏幕像素的坐…

非科班菜鸡算法学习记录 | 代码随想录算法训练营第58天|| 单调栈! 739. 每日温度 496.下一个更大元素 I

739. 每日温度 输入一个数组&#xff0c;找比i天温度高的第一天 知识点&#xff1a;单调栈 状态&#xff1a;看思路自己写 思路&#xff1a; 看自己写的注释&#xff0c;维护一个单调栈 // 版本一 class Solution { public:vector<int> dailyTemperatures(vector<…

视频导出文件太大如何变小?缩小视频这样做

作为一名视频制作爱好者&#xff0c;我们经常需要导出视频文件&#xff0c;但是&#xff0c;有时候我们会发现导出的视频文件太大&#xff0c;给上传和分享带来很大的不便。那么&#xff0c;如何将视频文件变小呢&#xff1f;下面将为你介绍三个方法&#xff0c;让你轻松解决视…

React 18 使用 Context 深层传递参数

参考文章 使用 Context 深层传递参数 通常来说&#xff0c;会通过 props 将信息从父组件传递到子组件。但是&#xff0c;如果必须通过许多中间组件向下传递 props&#xff0c;或是在应用中的许多组件需要相同的信息&#xff0c;传递 props 会变的十分冗长和不便。Context 允许…

Web后端开发(请求响应)上

请求响应的概述 浏览器&#xff08;请求&#xff09;<--------------------------(HTTP协议)---------------------->&#xff08;响应&#xff09;Web服务器 请求&#xff1a;获取请求数据 响应&#xff1a;设置响应数据 BS架构&#xff1a;浏览器/服务器架构模式。…

阿里云部署开源MQTT平台mosquitto的docker操作

MQTT&#xff08;Message Queuing Telemetry Transport&#xff09;是一种轻量级的消息传输协议&#xff0c;广泛用于物联网和传感器网络中。Mosquitto是一个流行的开源MQTT代理&#xff0c;可以在Docker中进行配置和部署。本文将详细介绍如何在Docker中配置Mosquitto MQTT代理…