UI自动化测试重点思考(下)--装饰器/生成器/夹具的使用/描述符的作用/ddt驱动/多线程
UI自动化测试重点思考--装饰器
- 装饰器
- 装饰器定义
- 装饰器代码示例
- 装饰器的执行
- 如何将装饰器融合到pytest框架里面
- 生成器
- 创建生成器
- 生成器的定义
- 如何将生成器融合到pytest框架里面
- fixture(夹具)使用
- pytest fixture 中 scope 参数的详细解释
- 描述符的总结
- 描述符的定义
- 描述符的作用
- ddt数据驱动
- 简单示例
- 升级示例
- 多线程
- 安装pytest-xdist 插件
- 采用多线程编程
装饰器
装饰器定义
装饰器是一个函数A,函数A的传参是函数B,且函数A内部还有一个函数C,且函数A返回一个函数C,函数C是包含函数B的。
装饰器代码示例
def my_decorator(func):def wrapper():print("Something is happening before the function is called.")func()print("Something is happening after the function is called.")return wrapper@my_decorator
def say_hello():print("Hello!")say_hello()
在这个例子中,my_decorator 是一个装饰器函数,它接受一个函数作为参数。wrapper 函数是由装饰器内部定义的一个新函数,它包裹了原始的 say_hello 函数,并添加了额外的功能。当调用 say_hello() 时,实际上是调用了 wrapper 函数,从而触发了装饰器中定义的操作。
装饰器的执行
- 当 Python 解释器执行到
@my_decorator
时,它会立即将被装饰的函数say_hello
传递给my_decorator
函数,相当于执行了say_hello = my_decorator(say_hello)
。 - 在 my_decorator 函数内部,它定义了一个内部函数
wrapper
,该函数包含了在被装饰函数调用前后需要执行的逻辑。 - 当调用
say_hello()
时,实际上是调用了wrapper()
函数,因为 say_hello 已经被重新指向了 wrapper 函数。 - 在 wrapper 函数内部,首先会执行装饰器定义的
前置逻辑
,然后调用被装饰的函数 func()
,即调用原始的 say_hello 函数。 - 在调用完被装饰函数后,继续执行 wrapper 函数中的
后置逻辑
。
如何将装饰器融合到pytest框架里面
1.全局管理 driver,运行测试用例的时候先调用 driver 传入测试用例中,测试用例就可以使用 driver来操作浏览器了。
2.实现执行测试用例之前先登录或者先打开网址,执行测试用例之后再自动登出的操作。
生成器
创建生成器
- 生成器推导式
gen = (x ** 2 for x in range(1, 6))
- 含有yield关键字
def squares(n):for i in range(1, n + 1):yield i ** 2print("这里被挤出了一个糖")
gen=squares(5)
定义了一个名为 squares 的函数,该函数接受一个整数 n 作为参数。在函数内部,使用 yield 语句来生成从 1 到 n 的整数的平方值,并在最后打印一条信息 “这里被挤出了一个糖”。
生成器的定义
1.只要是实现了yield关键字的函数都是一个生成器
2.生成器的特点是,当调用者执行到yield就会卡住,然后把yield后面的参数返回给调用者
3.当接收到next()函数的命令的时候才会执行yield关键字下面的代码
如何将生成器融合到pytest框架里面
1.自动登录登出中要使用生成器
实现了执行测试用例之前先执行前置操作【登录】【因为有装饰器】直到代码运行到有 yield 关键字的时候才会卡住,当执行完测试用例之后,pytest 自动调用 next 函数,才会去执行 yield 关键字后的后置操作【登出】。
fixture(夹具)使用
pytest fixture 中 scope 参数的详细解释
Scope 参数值 | 描述 |
---|---|
function | 每个测试函数都会调用一次 fixture 函数,并且在测试函数执行完毕后立即销毁。 |
class | 在测试类中的所有测试方法之间共享 fixture,fixture 在第一个测试方法运行前创建,在最后一个测试方法运行后销毁。 |
module | 在整个测试模块中共享 fixture,fixture 在第一个测试函数运行前创建,在最后一个测试函数运行后销毁。 |
session | 在整个 pytest 会话期间共享 fixture,fixture 在 pytest 启动时创建,在 pytest 结束时销毁。 |
描述符的总结
描述符的定义
描述符是实现了特定协议的类,它至少包含 get()、set() 和 delete() 中的一个方法。
描述符的作用
描述符可以用于控制对类的属性的访问、修改和删除,允许你在属性被访问、修改或删除时执行自定义的逻辑。
class PageElement:def __get__(self, instance, owner):print("Getting the value")return instance.__dict__.get(self.attr_name, None)def __set__(self, instance, value):print("Setting the value")instance.__dict__[self.attr_name] = valuedef __delete__(self, instance):print("Deleting the value")del instance.__dict__[self.attr_name]class Page:element = PageElement()def __init__(self):self.element = None@propertydef element(self):return self._element@element.setterdef element(self, value):self._element = value# 示例用法
page = Page()
page.element = "Hello" # 设置属性值,调用 PageElement.__set__()
print(page.element) # 获取属性值,调用 PageElement.__get__()
del page.element # 删除属性值,调用 PageElement.__delete__()
ddt数据驱动
简单示例
import pytest
import time@pytest.mark.smoke
@pytest.mark.parametrize('username, password', [('user1', 'DasSWOLd'),('user2', 'pass2'),('wzz', '12345')
])
def test_001(self, drivers, username, password):zhufeng = ZhuifengIndexPage(drivers)zhufeng.input_account(username)zhufeng.input_password(password)zhufeng.click_login_button()time.sleep(3)
- @pytest.mark.smoke:是一个 pytest 的标记,用于标记测试用例为 smoke 测试,表示这是一个简单的冒烟测试,主要验证系统的基本功能。
- @pytest.mark.parametrize(‘username, password’, […]):是 pytest 提供的一个装饰器,用于为测试用例提供多组参数数据。
- 测试用例 test_001(self, drivers, username, password):这是一个测试方法,其参数包括 drivers、usernausername 和 password 是测试数据,由 @pytest.mark.parametrize 提供。me 和 password。
升级示例
def read_csv_file(file_path):"""生成器方式去读取csv里面的数据来做数据驱动测试,yield关键字来控制一行一行的读取字典里面的内容(字典里面的数据是隐形的,还未产生,就和奶糖盒子一样的道理)"""with open(file_path, 'r', newline='') as file:reader = csv.DictReader(file) # 这是一个迭代器对象,把每次读取出来的数据都放到字典里面存起来,下面用一个for循环一次一次的去读取字典里面的数据,确保不会一次性将所有的数据读取到内存中。for row in reader: # 如过下面没有生成器,那么这里直接全部数据都遍历一遍,如果有生成器就会卡住,一个一个来,接收到next方法才会读取下一行。yield row['username'], row['password']@pytest.mark.smoke
@pytest.mark.parametrize('username, password', read_csv_file(r'data/data.csv'))
def test_001(drivers, username, password):zhufeng = zhuifeng_index_page(drivers)zhufeng.input_account = usernamezhufeng.input_password = password# zhufeng.log_in_button.click()zhufeng.click_log_in_button# assert drivers.current_url == 'https://exam.wzzz.fun'
1.read_csv_file 函数:
- 这是一个生成器函数,用于逐行读取 CSV 文件中的数据。使用 yield
关键字,每次从文件中读取一行数据
,并返回一个包含用户名和密码的元组。
- @pytest.mark.parametrize(‘username, password’, read_csv_file(r’data/data.csv’)):
- 使用 @pytest.mark.parametrize 装饰器标记测试用例,并提供了多组用户名和密码的数据源。
- 数据源来自于 read_csv_file 函数返回的生成器,通过调用 read_csv_file 函数来读取 CSV文件中的数据,并将其作为参数传递给测试用例。
3.def test_001(drivers, username, password): - 在测试方法中,首先创建了一个 zhufeng_index_page 对象,然后输入了用户名和密码,并点击了登录按钮(注释掉的部分)
- 这个测试方法会被 @pytest.mark.parametrize 多次调用,每次调用时传入不同的用户名和密码数据。
多线程
安装pytest-xdist 插件
pip install pytest-xdist
采用多线程编程
1、可以使用 threading 线程来指定要并发执行的测试用例,但是用例数量一旦多了,就不好去人工分配哪一个线程执行那部分用例,这时候可以使用插件 pytest-xdist,执行 pytest-n5就好了,使用多少个线程并发执行还是得看电脑性能如何,一般使用10~20 个线程为最佳,在自己电脑上就使用5个线程就好了。
2、多线程并发执行用例,相当于多个人同时进行测试,宏观上是这样的,不过微观上对于 cpu 都是串行的,只是调度每一个线程的速度非常快,看起来是并发的而己,因为只有一个cpu,同一时刻,只能执行一个线程,如果有多个cpu 才能真正意义上实现多个测试用例并发执行,不过对于测试而言,无伤大雅,我们了解原理即可,我们主要重在使用。
相关文章:

UI自动化测试重点思考(下)--装饰器/生成器/夹具的使用/描述符的作用/ddt驱动/多线程
UI自动化测试重点思考--装饰器 装饰器装饰器定义装饰器代码示例装饰器的执行如何将装饰器融合到pytest框架里面 生成器创建生成器生成器的定义如何将生成器融合到pytest框架里面 fixture(夹具)使用pytest fixture 中 scope 参数的详细解释 描述符的总结描…...

C# 字段和属性的区别
区别 在C#中,字段(Field)和属性(Property)都是用来封装对象状态的方式,但它们有以下区别: 访问级别: 字段通常是private,而属性可以有不同级别的访问限制(…...

备考ICA----Istio实验17---TCP流量授权
备考ICA----Istio实验17—TCP流量授权 1. 环境准备 1.1 环境部署 kubectl apply -f <(istioctl kube-inject -f istio/samples/tcp-echo/tcp-echo.yaml) -n kim kubectl apply -f <(istioctl kube-inject -f istio/samples/sleep/sleep.yaml) -n kim1.2 测试环境 检测…...
[C++][算法基础]树的重心(树图DFS)
给定一颗树,树中包含 n 个结点(编号 1∼n)和 n−1 条无向边。 请你找到树的重心,并输出将重心删除后,剩余各个连通块中点数的最大值。 重心定义:重心是指树中的一个结点,如果将这个点删除后&a…...

探秘ChatGPT:如何利用AI提升论文写作效率
ChatGPT无限次数:点击直达 html 探秘ChatGPT:如何利用AI提升论文写作效率 在当今信息爆炸的时代,论文写作是许多人工作者每天都要面对的任务。如何更高效地撰写出内容丰富、结构严谨的论文,一直是许多学者和研究人员所追求的目标。随着人…...

多无人机集群协同避障
matlab2020a正常运行 场景1规划结果 场景2规划结果 场景3规划结果 代码地址: 多无人机集群协同避障效果(5架)资源-CSDN文库...

基于velero和minio实现k8s数据的备份
1.30部署minio rootk8s-harbor:/etc/kubeasz/clusters/k8s-cluster1# docker run \ -d --restartalways -p 9000:9000 -p 9090:9090 –name minio -v /data/minio/data:/data -e “MINIO_ROOT_USERadmin” -e “MINIO_ROOT_PASSWORD12345678” quay.io/minio/minio server…...

【Java核心技术】第4章 对象与类
1 面向对象 2 自定义类 形式: class ClassName { field // 字段 constructor // 构造器(构造函数) method // 方法 } 如: class Employee {private String name;private double salary;private LocalDate hireDay;public Emp…...

【LeetCode】回溯算法类题目详解
所有题目均来自于LeetCode,刷题代码使用的Python3版本 回溯算法 回溯算法是一种搜索的方法,在二叉树总结当中,经常使用到递归去解决相关的问题,在二叉树的所有路径问题中,我们就使用到了回溯算法来找到所有的路径。 …...

java实现请求缓冲合并
业务背景: 我们对外提供了一个rest接口给第三方业务进行调用,但是由于第三方框架限制,导致会发送大量相似无效请求,例如:接口入参json包含两个字段,createBy和receiverList,完整的入参json示例…...

分布式锁的原子性问题
4.6 分布式锁的原子性问题 更为极端的误删逻辑说明: 线程1现在持有锁之后,在执行业务逻辑过程中,他正准备删除锁,而且已经走到了条件判断的过程中,比如他已经拿到了当前这把锁确实是属于他自己的,正准备删…...

从零自制docker-8-【构建实现run命令的容器】
文章目录 log "github.com/sirupsen/logrus"args...go moduleimport第三方包失败package和 go import的导入go build . 和go runcli库log.SetFormatter(&log.JSONFormatter{})error和nil的关系cmd.Wait()和cmd.Start()arg……context.Args().Get(0)syscall.Exec和…...

2024.03.31 校招 实习 内推 面经
绿*泡*泡VX: neituijunsir 交流*裙 ,内推/实习/校招汇总表格 1、自动驾驶一周资讯 -小米SU7上市24小时,大定达88898台;小鹏汽车正式进入德国市场;地平线递交港股上市申请 自动驾驶一周资讯 -小米SU7上市24小时&…...

邦芒职场:塑造职场人气王的秘诀
在职场中,有些人总能吸引众人的目光,成为团队的焦点;而有些人却常常默默无闻,难以融入。那么,如何在职场中脱颖而出,成为一个受欢迎的人呢?下面,让我们来探讨一下塑造职场人气王的秘…...

滤波器网络变压器的作用
网络变压器的作用主要包括以下几点: 1. 信号传输:网络变压器可以将PHY送出来的差分信号用差模耦合的线圈耦合滤波以增强信号,并且通过电磁场的转换耦合到不同电平的连接网线的另外一端以达到传输数据的目的。 2. 电气电压隔离:…...

Python —— 简述
Houdini Python | 笔记合集 - 知乎 Houdini内置三大语言: 表达式,主要用于节点参数控制,可实现跨模块控制;vex,速度最快(比表达式和Python快一个数量级),非常适合密集型计算环境&…...

使用Rust加速Python程序,让代码飞起来
作为一种解释型语言,Python在开发速度和灵活性方面具有明显的优势,但在性能方面却不如编译型语言如C或Rust。对于性能要求苛刻的应用程序,如果纯粹使用Python编写可能会运行缓慢,影响用户体验。因此,如何利用Rust来加速…...

【RISC-V 指令集】RISC-V 向量V扩展指令集介绍(八)- 向量整数算术指令
1. 引言 以下是《riscv-v-spec-1.0.pdf》文档的关键内容: 这是一份关于向量扩展的详细技术文档,内容覆盖了向量指令集的多个关键方面,如向量寄存器状态映射、向量指令格式、向量加载和存储操作、向量内存对齐约束、向量内存一致性模型、向量…...

Qt Designer在布局中调整控件垂直伸展或者水平伸展之后控件没有变化
QtDesigner设置垂直伸展 在Qt Designer中,要对网格布局中的每一个网格设置垂直伸展,可以按照以下步骤操作: 1.打开Qt Designer并打开你的UI文件。 2.确保你的布局是一个网格布局(QGridLayout)。 3.选中你想要设置垂直…...

微信公众号粉丝迁移费用是多少?
公众号迁移后原来内容还在么?通过公众号迁移,可以实现这些目的:主体变更、开通留言功能、多号合并、订阅号升级为服务号、服务号转为订阅号。公众号迁移流程:①申请公证;②提交迁移申请;③第三方审核&#…...

基于Vue3 中后台管理系统框架
基于Vue3 中后台管理系统框架 文章目录 基于Vue3 中后台管理系统框架一、特点二、源码下载地址 一款开箱即用的 Vue 中后台管理系统框架,支持多款 UI 组件库,兼容PC、移动端。vue-admin, vue-element-admin, vue后台, 后台系统, 后台框架, 管理后台, 管理…...

Agent调研--19类Agent框架对比
代理(Agent)指能自主感知环境并采取行动实现目标的智能体,即AI作为一个人或一个组织的代表,进行某种特定行为和交易,降低一个人或组织的工作复杂程度,减少工作量和沟通成本。 背景 目前,我们在探…...

蓝桥杯-求阶乘
问题描述 满足 N!的末尾恰好有 区 个o的最小的 N 是多少? 如果这样的 N 不存在输出 -1。 输入格式 一个整数 区。 输出格式 一个整数代表答案。 样例输入 样例输出 10 评测用例规模与约定 对于 30% 的数据,1<K<106 对于 100% 的数据,1<K<1018 运行限制 最大运行时…...

计算两个日期之间相差的天数的四种方法
计算两个日期之间相差的天数的四种方法 第一种:时间戳的方式,计算两个日期的时间戳的差,再除当天的毫秒数即可得到相差的天数。 public static void main(String[] args) {DateFormat dft new SimpleDateFormat("yyyy-MM-dd");t…...

【leetcode面试经典150题】42. 有效的字母异位词(C++)
【leetcode面试经典150题】专栏系列将为准备暑期实习生以及秋招的同学们提高在面试时的经典面试算法题的思路和想法。本专栏将以一题多解和精简算法思路为主,题解使用C语言。(若有使用其他语言的同学也可了解题解思路,本质上语法内容一致&…...

Windows 2003 R2与Windows 2022建立域信任报错:本地安全机构无法跟域控制器获得RPC连接。请检查名称是否可以解析,服务器是否可用。
在Windows Server 2003 R2与Windows Server 2022之间建立域信任时遇到“本地安全机构无法与域控制器获得RPC连接”的错误,可能是由于以下几种原因: DNS 解析问题: 确保源域和目标域的DNS配置正确,能够互相解析对方的域名和IP地址。…...

UE5、CesiumForUnreal实现加载建筑轮廓GeoJson数据生成白模功能
1.实现目标 在UE5.3中,通过加载本地建筑边界轮廓面GeoJson数据,获取底面轮廓和楼高数据,拉伸生成白模,并支持点选高亮。为防止阻塞Game线程,使用了异步任务进行优化,GIF动图如下所示: 其中建筑数量:128871,顶点索引数量:6695748,三角面数量:2231916,顶点数量:165…...

JavaGUI编程
目录 GUI概念 Swing概念 组件 容器组件 窗口(JFrame) 代码 运行 面板(JPanel) 代码 运行 布局管理器 FlowLayout 代码 运行 BorderLayout 代码 运行 GridLayout 代码 运行 常用组件 标签(JLabel) 代码 运…...

Nginx 基础应用实战 03 基于反向代理的负载均衡、https配置
Nginx 基础应用实战 03 反向代理 proxy_pass http://baidu.com; location /mashibing {proxy_pass http://mashibing.com/;}基于反向代理的负载均衡 upstream httpd {server 192.168.43.152:80;server 192.168.43.153:80; }weight(权重) 指定轮询几率,weight和访…...

[图解]DDD领域驱动设计伪创新-聚合根02
0 00:00:04,940 --> 00:00:06,993 在领域驱动设计之前 1 00:00:06,993 --> 00:00:09,503 的软件开发书籍里面 2 00:00:09,503 --> 00:00:12,470 并没有出现聚合根这样的说法 3 00:00:13,000 --> 00:00:14,840 大家可以去找一下 4 00:00:15,120 --> 00:00:15…...