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.选中你想要设置垂直…...
微信公众号粉丝迁移费用是多少?
公众号迁移后原来内容还在么?通过公众号迁移,可以实现这些目的:主体变更、开通留言功能、多号合并、订阅号升级为服务号、服务号转为订阅号。公众号迁移流程:①申请公证;②提交迁移申请;③第三方审核&#…...
Zustand 状态管理库:极简而强大的解决方案
Zustand 是一个轻量级、快速和可扩展的状态管理库,特别适合 React 应用。它以简洁的 API 和高效的性能解决了 Redux 等状态管理方案中的繁琐问题。 核心优势对比 基本使用指南 1. 创建 Store // store.js import create from zustandconst useStore create((set)…...
Linux简单的操作
ls ls 查看当前目录 ll 查看详细内容 ls -a 查看所有的内容 ls --help 查看方法文档 pwd pwd 查看当前路径 cd cd 转路径 cd .. 转上一级路径 cd 名 转换路径 …...
条件运算符
C中的三目运算符(也称条件运算符,英文:ternary operator)是一种简洁的条件选择语句,语法如下: 条件表达式 ? 表达式1 : 表达式2• 如果“条件表达式”为true,则整个表达式的结果为“表达式1”…...
JVM垃圾回收机制全解析
Java虚拟机(JVM)中的垃圾收集器(Garbage Collector,简称GC)是用于自动管理内存的机制。它负责识别和清除不再被程序使用的对象,从而释放内存空间,避免内存泄漏和内存溢出等问题。垃圾收集器在Ja…...
五年级数学知识边界总结思考-下册
目录 一、背景二、过程1.观察物体小学五年级下册“观察物体”知识点详解:由来、作用与意义**一、知识点核心内容****二、知识点的由来:从生活实践到数学抽象****三、知识的作用:解决实际问题的工具****四、学习的意义:培养核心素养…...
WEB3全栈开发——面试专业技能点P2智能合约开发(Solidity)
一、Solidity合约开发 下面是 Solidity 合约开发 的概念、代码示例及讲解,适合用作学习或写简历项目背景说明。 🧠 一、概念简介:Solidity 合约开发 Solidity 是一种专门为 以太坊(Ethereum)平台编写智能合约的高级编…...
多种风格导航菜单 HTML 实现(附源码)
下面我将为您展示 6 种不同风格的导航菜单实现,每种都包含完整 HTML、CSS 和 JavaScript 代码。 1. 简约水平导航栏 <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport&qu…...
ip子接口配置及删除
配置永久生效的子接口,2个IP 都可以登录你这一台服务器。重启不失效。 永久的 [应用] vi /etc/sysconfig/network-scripts/ifcfg-eth0修改文件内内容 TYPE"Ethernet" BOOTPROTO"none" NAME"eth0" DEVICE"eth0" ONBOOT&q…...
【数据分析】R版IntelliGenes用于生物标志物发现的可解释机器学习
禁止商业或二改转载,仅供自学使用,侵权必究,如需截取部分内容请后台联系作者! 文章目录 介绍流程步骤1. 输入数据2. 特征选择3. 模型训练4. I-Genes 评分计算5. 输出结果 IntelliGenesR 安装包1. 特征选择2. 模型训练和评估3. I-Genes 评分计…...
脑机新手指南(七):OpenBCI_GUI:从环境搭建到数据可视化(上)
一、OpenBCI_GUI 项目概述 (一)项目背景与目标 OpenBCI 是一个开源的脑电信号采集硬件平台,其配套的 OpenBCI_GUI 则是专为该硬件设计的图形化界面工具。对于研究人员、开发者和学生而言,首次接触 OpenBCI 设备时,往…...
