如何在自动化测试中应用装饰器、多线程优化自动化架构?

1、装饰器概念

        装饰器是Python中用于修改函数或类的语法结构的工具。它以函数作为输入参数,并返回一个函数作为一个输出函数,在不改变原有函数的代码情况下,给函数增加功能或改变函数行为。

        装饰器的使用方式是在函数定义的上方使用 @decorator_name 的形式将装饰器应用到函数上,这样定义的函数在被调用时会先执行装饰器函数,再执行原始函数。常见的装饰器有类装饰器、函数装饰器、属性装饰器等。

        装饰器本身需要接受一个被装饰的对象作为参数,该参数通常为函数、方法、类等对象。

        装饰器需要返回一个对象,该对象可以是 经过处理的原参数对象、一个包装且类似原参数的对象

1.1 最简单的装饰器

def my_decorator(func):def wrapper():print("Before the function is called.")func()print("After the function is called.")return wrapper@my_decorator
def say_hello():print("Hello!")say_hello()

 如代码所示:

1、当我们调用被装饰器修饰的函数的时候,首先会把 say_hello 的函数传入 my_decorator
的 func 参数中,然后再去执行内部的 wrapper 函数(在这个函数内部就会操作很多东西,比如增删改等操作),最后返回 wrapper 函数。

2、实际上我们调用的 say helo 函数没有被执行,那这里为什么执行了呢?是因为 wrapper函数里面又调用了一次它,如果不调用,那么 say hello 函数就是一个装饰,但是通常情况下都会调用一次来达到我们的一些特殊目的。

1.2 用于修改对象和函数的装饰器 

def wrap(obj):obj.name = 'python'return obj@wrap
class Bar(object):def __init__(self, name):passprint(Bar.name)@wrap
def foo():passprint(foo.name)

 可以看到实际的使用过程中,warp装饰器已经成功的给Bar对象添加了name属性。除了给类对象添加属性之外,它还可以给函数对象添加属性。

1.3 用于模拟对象的装饰器-函数装饰器【重点中的重点】

用于模拟对象的装饰器--函数装饰器
上面例子中的装饰器,是直接修改了传入对象,而装饰器最常用的方式却是模拟一个传入对象。即返回一个和原对象相似的对象(即调用接口完全一样的另一个对象),并且该模拟对象是包装了原对象在内的。具体代码如下:

def outer(func):def inner():print("Hello inner")func()return inner
@outer
def foo():print("Hello foo")print(foo.__name__)
foo()

上面是一个函数装饰器,即用来修饰函数的装饰器因为它返回了一个模拟func对象的inner对象。而这里inner对象是一个函数,所以这个装饰器只能装饰函数。(因为inner对象只能模拟func这样的函数对象,不能模拟class对象)
可以看到首先打印的是 foo._name_代码,注意内容是inner而不是foo(说明其本质上是inner函数);其次打印的时候,先打印inner函数中的内容,后打印foo函数中的内容。

Python 中被装饰后的函数,函数名等函数属性会发生改变(相当于另一个函数了)所以,Python 的functools 包中提供了一个叫 wraps 的装饰器来解决该问题。它能使其保留原有函数的结构。 

1.4 用于模拟对象的装饰器

def outer(obj):def inner(self):print('hello inner')obj(self)return innerclass Zoo(object):def _init_(self):pass@outerdef zoo(self):print('hello zoo')
zoo = Zoo()
print(zoo.zoo.__name__)
zoo.zoo()

 可以看到类方法装饰器和函数装饰器,唯一的区别是多了一个默认的self参数,这是因为类方法本身比函数多一个参数。

2、装饰器的应用

Python 装饰器的应用比较广泛,大部分场景的公共处理逻辑都可以使用装饰器去简化。(使用上类似于 JAVA 中的注解)一般比较常见的场景比如:

  • 日志记录
  • 权限验证
  • 单例模式
  • 竞争资源管理
  • Fixture

2.1 装饰器在pytest中的使用@pytest.fixture 

        比如 conftest 胶水文件中可以写 driver 以及写数据库连接操作等,使用装饰器+生成器假设我们有一个需要连接数据库执行查询操作的测试用例集合。
        在每个测试用例执行前,我们需要先建立数据库连接,并在每个测试用例执行结束后,关闭数据库连接。这时,我们可以使用 @pytest.fixture 装饰器定义一个名为 db_conn 的fixture 函数,它返回一个数据库连接对象,然后在测试用例函数中通过参数引用该 fixture函数即可获得连接对象。
        我们可以非常方便地对测试用例进行初始化和清理工作,避免几余代码,并且可以重复利用测试代码和资源。
代码示例如下: 

import pytest
import psycopg2
@pytest.fixture(scope='function')
def db_conn():conn = psycopg2.connect(database="testdb",user="testuser",
password="testpass'host="localhost",port="5432")yield connconn.close()def test_query1(db_conn):cursor =db_conn.cursor()cursor.execute('SELECT * FROM table1')result = cursor.fetchall()assert len(result)>0def test_query2(db_conn):cursor=db_conn.cursor()cursor.execute('SELECT * FROM table2')result = cursor.fetchall()assert len(result)>0

2.2 pytest中的@pytest.mark 

它可用于给测试用例打标签,方便统计测试结果和过滤测试用例。比如,给测试用例打上 slow、fast、smoke 等标签,可以通过 pytest 的命令行参数 pytest -m 进行选择性测试。

import pytest@pytest.mark.slow
def test_case1():pass@pytest.mark.fast
def test_case2():pass@pytest.mark.smoke
def test_case3():pass

pytest .\1.py -m smoke 

 

如图,只有标记为smoke的被执行了 

2.3 @pytest.mark.paramsmetrize在pytest中的使用(参数化)

它可用于参数化测试用例,即对同一种情况下的不同输入进行测试,可以减少重复的测试代码和测试用例数量。

import pytest
@pytest.mark.parametrize('a, b,c',[(1,2,3),(4,5,9),(7,8, 15)])
def test add(a, b, c):assert a+b==C 

 2.4 pytest中的@pytest.hookimpl中的使用

它可以定义 pytest 的 hook 函数,hook 函数用于在 pytest 的执行过程中被调用,以处理测试收集、运行、报告等各个环节。
 

import pytest
@pytest.hookimpl
def pytest runtest call(item):print(f"test function fitem.name} is about to run...")

把这个函数放到 conftest 中就可以实现功能了

 每当我们跑一个用例,就会打印一些日志内容

2.5 python 的@property 装饰器的介绍与使用

python 的@property 是 python 的一种装饰器,是用来修饰方法的。

作用:
我们可以使用@property 装饰器来创建只读属性,@property 装饰器会将方法转换为相同名称的只读属性,可以与所定义的属性配合使用,这样可以防止属性被修改。 

简而言之:

1.可以把方法变为属性

2.防止属性被修改

class DataSet(object):@propertydef method _with_property(self):
##含有@propertyreturn 15def method without property(self):##不含@propertyreturn 15
I= DataSet()
print(l.method with _property)
#加了@property 后,可以用调用属性的形式来调用方法,后面不需要加()
print(l.method without property())
#没有加@property,必须使用正常的调用方法的形式,即在后面加()

3、多线程编程思想 

1、如果你的测试用例是 I/O 密集型的,比如页面加载、数据输入等操作,那么使用多线程可以显著提高测试执行的效率。因为在等待I/O操作完成的时间内,可以切换到其他线程执行任务,避免浪费 CPU 资源,简单来说就是频繁输入加载等操作,就很适合多线程,不过要注意电脑的配置
2、如果你的测试用例需要在不同的浏览器或者不同的页面之间进行切换,那么使用多
线程可以避免在切换时出现页面卡顿或者响应延迟的问题。

3、如果除开这上面的操作,如果强行使用多线程开发,可能还会导致性能下降,因为需要频繁去调度 cpu,切换线程,线程间切换的开销可能会抵消掉并行处理所获得的性能提升

使用方法:使用 pytest-xdist 插件来实现多线程并发执行测试用例(自动分配每个线程要执行哪些测试用例)

当运行测试时,pytest-xdist 插件会自动将测试用例分发给多个线程并发执行,每个线程都可以独立打开一个网页运行测试用例,从而提高整体的执行效率。
使用 pytest 单线程运行测试用例:

pytest无头模式

在无头模式中,五个用例执行快了四秒,我为每一个用例都分配了一个线程去执行,这样会更快,因为会并发的去执行这五个测试用例。cpu不断的调度实现宏观的并发,微观实际上还是并行)
在有头模式中,打开了五个浏览器一起执行 88 个测试用例,相当于五个人一起执行测试用例,速度肯定是更快的,快了30s。(cpu不断的调度实现宏观的并发,微观实际上还是并行)
用法详解:
1、pytest-n 2:使用 2 个进程并行运行测试,如果有四个用例,1,3用例给第一个线程执行,2,4用例给第二个线程执行。
2、pytest -n auto:自动检测可用的 CPU 核心数量,并使用对应数量的进程并行运行测试。这是一种常用的设置,可以充分利用计算资源。
3、pytest -n 4-dist=loadfile:使用 4个进程并行运行测试,并使用"oadfile"分发插件进行测试运行。
使用 -n 参数,pytest 可以在多个进程中同时执行测试,从而加快整体测试运行时间,特别是在拥有多个 CPU 核心或处理器的计算机上。建议在实际使用时,根据自己的系统配置和测试需求,调整-n参数的值来获得最佳的性能和效果

4、数据驱动测试,yaml数据源 

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

re题(30)BUUCTF-[HDCTF2019]Maze

BUUCTF在线评测 (buuoj.cn) 查一下壳,32位upx壳 脱完壳放到ida,shiftF12看一下字符串,是个迷宫,maze(迷宫) 这里有一个经典的花指令 (导致找不到main函数) 下方有个奇怪的jnz指令,它跳转到了下…

[数据结构]算法复杂度详解

文章目录 一、引言1、想象数据结构与算法的奇妙世界2、算法复杂度的轻松解读3、数据结构与算法的温馨寄语 二、轻松掌握复杂度基础1、时间复杂度:算法速度的衡量尺2、空间复杂度:算法占地的衡量尺3、常见的复杂度 三、复杂度的计算1、时间复杂度计算2、空…

加密与安全_优雅存储二要素(AES-256-GCM )

文章目录 什么是二要素如何保护二要素(姓名和身份证)加密算法分类场景选择算法选择AES - ECB 模式 (不推荐)AES - CBC 模式 (推荐)GCM(Galois/Counter Mode)AES-256-GCM简介AES-256-GCM工作原理安全优势 应用场景其他模式 和 敏感…

【CSS】选择器(基础选择器、复合选择器、属性匹配选择器、结构伪类选择器、伪元素选择器)

选择器 引入方式基础选择器复合选择器属性匹配选择器结构伪类选择器伪元素选择器 引入方式 1&#xff1a;外联 <!-- css引入方式1&#xff1a;外联 外联与内嵌优先级相同&#xff0c;取决于加载顺序 --><link rel"stylesheet" type"text/css" h…

echarts 自定义标注样式自定义tooltip弹窗样式

文章目录 1. 实现根据经纬度自定义标注图片样式2. 实现鼠标悬浮标注自定义弹窗样式内容 1. 实现根据经纬度自定义标注图片样式 设置 symbol 属性为 image://${require("/assets/img/dataView/point.png")} 图片地址即可&#xff0c;注意前面跟 image:// 特有的写法b…

【数一线性代数】007入门

Index 本文稍后补全&#xff0c;推荐阅读&#xff1a;https://blog.csdn.net/weixin_60702024/article/details/140939599分析实现总结 本文稍后补全&#xff0c;推荐阅读&#xff1a;https://blog.csdn.net/weixin_60702024/article/details/140939599 用两个栈来实现一个队列…

Redis学习以及SpringBoot集成使用Redis

目录 一、Redis概述 二、Linux下使用Docker安装Redis 三、SpringBoot集成使用Redis 3.1 添加redis依赖 3.2 配置连接redis 3.3 实现序列化 3.4 注入RedisTemplate 3.5 测试 四、Redis数据结构 一、Redis概述 什么是redis&#xff1f; redis 是一个高性能的&#xf…

数据库恢复技术详解【从基础冗余数据到故障恢复的全过程】

在数据库系统中&#xff0c;数据的安全性和一致性至关重要。无论是面对事务故障、系统故障还是介质故障&#xff0c;数据库都需要具备强大的恢复机制来应对这些潜在风险。本文将带领大家详细了解数据库恢复的实现技术&#xff0c;重点介绍如何利用冗余数据、转储和日志文件来实…

Cpp快速入门语法(下)(2)

文章目录 前言一、函数重载概念与使用C为何支持函数重载&#xff1f; 二、引用概念语法特性权限(常引用)使用场景与指针的区别 三、内联函数四、auto关键字(C11)五、基于范围的for循环(C11)六、指针空值nullptr(C11)总结 前言 承前启后&#xff0c;正文开始&#xff01; 一、函…

【BFS专题】— 解决拓扑排序问题

拓扑排序介绍&#xff1a; 1、课程表 - 力扣&#xff08;LeetCode&#xff09; 思路&#xff1a; 通过Map<Integer, List<Integer>> 来创建邻接图&#xff0c;数组来表示入度然后遍历课程数组&#xff0c;建图然后再拓扑排序&#xff0c;bfs最后在遍历入度数组&…

14届蓝桥杯嵌入式国赛

目录 前言&#xff1a; 1.使用CUbeMX进行基础初始化配置 &#xff08;1&#xff09;选则芯片与基本初始化 &#xff08;2&#xff09;LED配置 &#xff08;3&#xff09;按键配置 &#xff08;4&#xff09;定时器和PWM以及频率 &#xff08;5&#xff09;ADC电压检测 …

计算机网络 --- 初识协议

序言 上一篇文章中 &#xff08;&#x1f449;点击查看&#xff09;&#xff0c;我们简单的了解了怎么寻找目标计算机&#xff0c;需要通过交换机&#xff0c;路由器等设备跨越多个网络来不断的转发我们需要传输的数据&#xff0c;直至到达目标计算机。  那我们设备之间数据是…

JMeter 中使用 Gson 操作请求中的Boby参数

背景 使用org.json.JSONObject 转换&#xff0c;与原Body参数顺序发生变化&#xff0c;原因&#xff1a;JSONObject内部是用Hashmap来存储的&#xff0c;本质上是一个无序的键值对集合&#xff0c;不应依赖字段的添加顺序。 为解决org.json.JSONObject 输出顺序问题&#xff…

鸿蒙读书笔记2:《鸿蒙操作系统设计原理与架构》

2. OS基础平台部件化 &#xff08;1&#xff09;内核层 内核层包括内核部件和HDF驱动框架部件。当前已提供LiteOS-M、 LiteOS-A、Linux和UniProton这4种内核部件&#xff0c;未来还可增加更多类 型的内核部件。LiteOS、Linux内核部件可以按需部署在不同设备之 上&#xff0c;内…

echarts X轴文本太长 formatter自定义文本的显示方式

如果ECharts中X轴的文本太长&#xff0c;可以通过设置axisLabel的rotate属性来旋转标签&#xff0c;或者使用formatter函数来自定义文本的显示方式。另外&#xff0c;可以开启axisLabel的interval属性来控制显示的标签的间隔。 option {tooltip: {},xAxis: {type: category,d…

p14 使用阿里云服务器的docker部署NGINX

拉取NGINX的镜像 这里因为之前已经配置过从阿里云的镜像仓库里面拿镜像所以这里直接就执行docker pull nginx拉取NGINX镜像就OK了 运行NGINX镜像 这里执行docker run -d --name nginx01 -p 3344:80 nginx这里3344是服务器访问的端口80是容器内部的端口&#xff0c;可以看到…

【C++ Primer Plus习题】16.5

大家好,这里是国中之林! ❥前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站。有兴趣的可以点点进去看看← 问题: 解答: #include <iostream> #include <list> using namespace…

硬件工程师笔试面试——集成电路

目录 17、集成电路 17.1 基础 集成电路实物图 17.1.1 概念 17.1.2 集成电路的发展历程 17.1.3 集成电路的分类 17.1.4 集成电路的制造工艺 17.1.5 集成电路的应用 17.2 相关问题 17.2.1 集成电路的制造工艺中,光刻技术是如何实现的? 17.2.2 在集成电路设计中,如何…

微信电脑版聊天图片DAT格式文件转为普通JPG图片

1-7 本文章主要教你如何恢复微信聊天中的聊天图片&#xff0c;主要应用场景是&#xff0c;当你的微信被封号了&#xff0c;或者无法登录了&#xff0c;会导致微信聊天中的聊天图片没办法再打开&#xff0c;如果是重要的图片&#xff0c;那就有损失了&#xff0c;所以有了本文的…

【无人机设计与控制】四旋翼无人机轨迹跟踪及避障Matlab代码

摘要 本文主要研究了四旋翼无人机在复杂环境中的轨迹跟踪与避障控制策略。通过Matlab/Simulink对四旋翼无人机进行了建模与仿真。系统集成了避障算法&#xff0c;使得无人机在执行任务时能够有效避开障碍物&#xff0c;保证飞行的安全性与稳定性。 理论 无人机飞行控制通常涉…