【pytest】tep环境变量、fixtures、用例三者之间的关系
tep是一款测试工具,在pytest测试框架基础上集成了第三方包,提供项目脚手架,帮助以写Python代码方式,快速实现自动化项目落地。
在tep项目中,自动化测试用例都是放到tests目录下的,每个.py文件相互独立,没有依赖,1个文件即1条用例,彼此分离。
虽然用例也能相互引用,但是除非万不得已,一般不建议这么做,牵一发动全身,后期维护困难。
用例的代码编写,思路是从上往下的,和pytest/unittest/script常规写法无异,不会有学习成本,一般也不会有问题。有成本有问题的可能是环境变量和fixtures,因为tep做了封装,提供了依赖注入的共享方式,fixture又是pytest较难理解的知识点,所以有必要通过本文来讲讲tep环境变量、fixtures、用例三者之间的关系,帮助理解,以便更灵活顺手的借助tep实现pytest自动化项目。
假如不用环境变量和fixtures
假如不用环境变量和fixtures,是完全可以的!比如,在tests
下新建脚本login_test.py
:
from tep.client import requestdef test():response = request("post",url="https://qa.com/api/users/login",headers={"Content-Type": "application/json"},json={"username": "admin","password": "123456",})assert response.status_code < 400
请求接口https://qa.com/api/users/login
,断言响应状态码小于400。问题来了:url
固定,假如需要切换两个环境qa
和release
,该怎么办?
参数化
无论是做自动化测试还是性能测试,都会接触到参数化这个词。它是指把代码中的固定数据(硬编码)定义成变量,让每次运行时数据不一样,固定数据变为动态数据。动态数据的来源是变量、数据库、外部文件等。动态数据的类型一般是常量的字符串,也可以是函数,比如JMeter的函数助手,也可以是依赖注入,比如pytest的fixture。
依赖注入的fixture
“依赖注入是控制反转(IoC, Inversion of Control)的一种技术形式”,这句话出自维基百科,我也不知道什么意思,画个图简单表达下:
意思是,给client一个injector,client不需要做什么,就能用到service。
pytest的fixture实现了依赖注入,允许我们在不修改测试代码的情况下,引入fixture来额外添加一些东东。
对于url来说,域名是需要做参数化的,不同环境域名不同,所以tep把它做成了fixture,通过函数参数引入:
from tep.client import request
from tep.fixture import *def test(url): # 引入fixtureresponse = request("post",url=url("/api/users/login"),headers={"Content-Type": "application/json"},json={"username": "admin","password": "123456",})assert response.status_code < 400
tep.fixture.url
定义如下:
@pytest.fixture(scope="session")
def url(env_vars):def domain_and_uri(uri):if not uri.startswith("/"):uri = "/" + urireturn env_vars.domain + urireturn domain_and_uri
如果一眼就看懂了,恭喜你,如果一眼就看懵了,没关系。我会花功夫把它讲明白,它很关键!
把fixture当变量看
虽然从定义上看,fixture是用def
关键字定义的函数,但是理解上把它看做变量就可以了。比如:
import pytest@pytest.fixture
def name():return "dongfanger"
一般函数的用法是函数名加小括号,通过name()
才能得到"dongfanger"
。fixture不一样,以上定义可以理解为:
name = "dongfanger"
把"dongfanger"
赋值给name
,fixture名 = return值。通过变量name
就得到"dongfanger"
了。
既然是变量,那么就能随便赋值,str
、function
、class
、object
都行。比如在fixture内部定义个函数:
import pytest@pytest.fixture
def who():def get_name():return "dongfanger"return get_name
理解为把函数名get_name赋值给fixture名变量:
who = get_name
get_name是个函数名,需要加小括号get_name()才能得到"dongfanger"。who也必须通过who()才能得到"dongfanger"。再看tep.fixture.url是不是清楚些了:
@pytest.fixture(scope="session")
def url(env_vars):def domain_and_uri(uri):if not uri.startswith("/"):uri = "/" + urireturn env_vars.domain + urireturn domain_and_uri
理解为把函数名domain_and_uri
赋值给fixture名变量:
url = domain_and_uri
使用时通过url("/api")
得到域名和uri拼接后的结果。
第2行的def url(env_vars):
也有一个参数env_vars
,接下来继续解释。
fixture参数是其他fixture
fixture的参数只能是其他fixture。比如:
import pytest@pytest.fixture
def chinese_name():return "东方er"@pytest.fixture
def english_name(chinese_name):return "dongfanger"
调用english_name
,pytest会先执行参数里的其他fixture chinese_name
,然后执行自己english_name
。
如果把tep.fixture.url
拆成两步来看,就很清晰了,第一步:
@pytest.fixture(scope="session")
def url(env_vars):func = Nonereturn func
第二步:
@pytest.fixture(scope="session")
def url(env_vars):func = Nonedef domain_and_uri(uri):if not uri.startswith("/"):uri = "/" + urireturn env_vars.domain + urifunc = domain_and_urireturn func
环境变量
tep.fixture.url
的参数是另外一个fixture env_vars
环境变量,它的定义如下:
from tep.fixture import *@pytest.fixture(scope="session")
def env_vars(config):class Clazz(TepVars):env = config["env"]"""Variables define start"""# Environment and variablesmapping = {"qa": {"domain": "https://qa.com",},"release": {"domain": "https://release.com",}# Add your environment and variables}# Define properties for auto displaydomain = mapping[env]["domain"]"""Variables define end"""return Clazz()
只看中间注释"""Variables define start"""到"""Variables define end"""部分即可。url参数化的域名就在这里,mapping字典建立了环境和变量之间的映射,根据不同的环境key,获取不同的变量value。
config fixture的作用是读取conf.yaml文件里面的配置。
参数化的方式很多,JMeter提供了4种参数化方式,tep的fixture env_vars
借鉴了JMeter的用户自定义变量:
env_vars.put()
和env_vars.get()
借鉴了JMeter BeanShell的vars.put()
和vars.get()
。
实例:测试多个网址
讲到最后,形成了思路,通过实际的例子,看看环境变量、fixtures、用例是怎么用起来的,加深下印象。假如qa
环境有2个网址,学校端和机构端,脚本都需要用到。
第一步修改env_vars
,编辑fixture_env_vars.py
:
"""Variables define start"""# Environment and variablesmapping = {"qa": {"domain": "https://qa.com","domain_school": "https://school.qa.com", # 新增"domain_org": "https://org.qa.com" # 新增},"release": {"domain": "https://release.com","domain_school": "https://school.release.com" # 新增"domain_org": "https://org.release.com" # 新增}# Add your environment and variables}# Define properties for auto displaydomain = mapping[env]["domain"]domain_school = mapping[env]["domain_school"] # 新增domain_org = mapping[env]["domain_org"] # 新增"""Variables define end"""
添加了6行代码,定义了env_vars.domain_school
和env_vars.domain_org
。
第二步定义fixtures,新建fixture_url.py
:
@pytest.fixture(scope="session")
def url_school(env_vars):def domain_and_uri(uri):if not uri.startswith("/"):uri = "/" + urireturn env_vars.domain_school + urireturn domain_and_uri@pytest.fixture(scope="session")
def url_org(env_vars):def domain_and_uri(uri):if not uri.startswith("/"):uri = "/" + urireturn env_vars.domain_org + urireturn domain_and_uri
参照tep.fixture.url,修改env_vars.domain为env_vars.domain_school和env_vars.domain_org,新增了2个fixture url_school和url_org。
更进一步,也许会定义fixture login_school和login_org,灵活选择。
小结
本文循序渐进的讲解了tep环境变量、fixtures和用例之间的关系,重点对tep.fixture.url进行了解释,只要理解了它,整体关系就很清楚了。之所以要用fixture,原因一是多人协作共享,我们需要用别人写好的函数,复用返回值,有些同学习惯定义函数参数,参数不变还好,万一哪天改了,别人引用的用例会全部报错,fixture很好的限制了这一点,它默认是不能传参的,虽然可以通过定义内部函数来实现传参,但是并不推荐这么做,宁愿增加冗余代码,定义多个fixture,也比代码耦合度高好一些。原因二是import的问题,pytest会自动查找conftest.py里的fixture,tep会进一步自动查找fixtures下的fixture导入到conftest.py,不需要import就能使用,减少了import代码,避免了可能会出现的循环导入问题。
最后感谢每一个认真阅读我文章的人,礼尚往来总是要有的,虽然不是什么很值钱的东西,如果你用得到的话可以直接拿走:
软件测试面试小程序
被百万人刷爆的软件测试题库!!!谁用谁知道!!!全网最全面试刷题小程序,手机就可以刷题,地铁上公交上,卷起来!
涵盖以下这些面试题板块:
1、软件测试基础理论 ,2、web,app,接口功能测试 ,3、网络 ,4、数据库 ,5、linux
6、web,app,接口自动化 ,7、性能测试 ,8、编程基础,9、hr面试题 ,10、开放性测试题,11、安全测试,12、计算机基础
这些资料,对于【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴上万个测试工程师们走过最艰难的路程,希望也能帮助到你!
相关文章:

【pytest】tep环境变量、fixtures、用例三者之间的关系
tep是一款测试工具,在pytest测试框架基础上集成了第三方包,提供项目脚手架,帮助以写Python代码方式,快速实现自动化项目落地。 在tep项目中,自动化测试用例都是放到tests目录下的,每个.py文件相互独立&…...

风控引擎如何快速添加模型,并实时了解运行状态?
目录 风控模型的主要类型 风控引擎如何管理模型? 模型就是基于目标群体的大规模采样数据,挖掘出某个实际问题或客观事物的现象本质及运行规律,利用抽象的概念分析存在问题或风险,计算推演出减轻、防范问题或风险的对策过程&…...

一文读懂|内核顺序锁
Linux 内核有非常多的锁机制,如:自旋锁、读写锁、信号量和 RCU 锁等。本文介绍一种和读写锁比较相似的锁机制:顺序锁(seqlock)。 顺序锁与读写锁一样,都是针对多读少写且快速处理的锁机制。而顺序锁和读写…...

openproject在docker下的安装
官方指引:https://www.openproject.org/docs/installation-and-operations/installation/docker/ 网友指引:https://blog.csdn.net/joefive/article/details/119409550 建个自己的数据文件夹: sudo mkdir -p /var/lib/openproject/{mydata…...

React【React是什么?、创建项目 、React组件化、 JSX语法、条件渲染、列表渲染、事件处理】(一)
文章目录 React是什么? 为什么要学习React React开发前准备 创建React项目 React项目结构简介 React组件化 初识JSX 渲染JSX描述的页面 JSX语法 JSX的Class与Style属性 JSX生成的React元素 条件渲染(一) 条件渲染 ࿰…...

Ubuntu系统下配置 Qt Creator 输入中文、配置软件源的服务器地址、修改Ubuntu系统时间
上篇介绍了Ubuntu系统下搭建QtCreator开发环境。我们可以发现安装好的QtCreator不能输入中文,也没有中文输入法供选择,这里需要进行设置。 文章目录 1. 配置软件源的服务器地址2. 先配置Ubuntu系统语言,设置为中文3. 安装Fcitx插件ÿ…...

Ab3d.PowerToys 11.0.8614 Crack
版本 11.0.8614 修补程序 使用 MouseCameraController 移动相机时防止旋转 FreeCamera。 版本 11.0.8585 重大更改:由于专利问题删除了 ViewCubeCameraController - 请联系支持人员以获取更多信息以及如果您想继续使用此控件。添加了 CameraNavigationCircles 控件…...

汽车3D HMI图形引擎选型指南【2023】
推荐:用 NSDT编辑器 快速搭建可编程3D场景 2002年,电影《少数派报告》让观众深入了解未来。 除了情节的核心道德困境之外,大多数人都对它的技术着迷。 我们看到了自动驾驶汽车、个性化广告和用户可以无缝交互的 3D 计算机界面。 令人惊讶的是…...

Stable Diffusion stable-diffusion-webui开发笔记
https://lexica.art/ lexica.art 该网站拥有数百万Stable Diffusion案例的文字描述和图片,可以为大家提供足够的创作灵感。可以提供promt灵感 https://civitai.com/ Civitai是一个聚集AI绘图爱好者的社区,在此网站上有许多定制化的模型,特…...

利用MQ实现mysql与elasticsearch数据同步
流程 1.声明exchange、queue、RoutingKey 2. 在hotel-admin中进行增删改(SQL),完成消息发送 3. 在hotel-demo中完成消息监听,并更新elasticsearch数据 4. 测试同步 1.引入依赖 <!--amqp--> <dependency><groupId&…...

linux免密登录最简单--图文详解
最简单的免密登录 1.A电脑生成秘钥 ssh-keygen -t rsa 2.A电脑将秘钥传给B电脑 ssh-copy-id root192.168.1.129 #将秘钥直接传给B电脑 需要输入B电脑的密码,可以看到成功。 3.测试 同理:如果B->A也需要免密登录,统一的操作。 大功告…...

HTTP/1.1协议中的请求报文
2023年8月30日,周三上午 目录 概述请求报文示例详述 概述 HTTP/1.1协议的请求报文由以下几个部分组成: 请求行(Request Line)请求头部(Request Headers)空行(Blank Line)请求体&a…...

攻防世界-Hear-with-your-Eyes
原题 解题思路 是一个没有后缀的文件,题目提示要用眼睛看这段音频,notepad打开文件,没什么东西。 加后缀zip再解压看看。 使用Audacity打开音频文件...

ZED相机获取图像python
import pyzed.sl as sl import cv2 import numpy as np import osclass CameraZed2:def __init__(self,resolutionNone,fps30,depthMode None):self.zed sl.Camera()self.input_type sl.InputType()self.init_params sl.InitParameters(input_tself.input_type)# 设置分辨率…...

Oracle系列之--Profile
Oracle系列之--Profile_oracle profile_楼兰过客的博客-CSDN博客...

学习Bootstrap 5的第四天
目录 表格 基础表格 实例 条纹表格 实例 带边框表格 实例 有悬停效果的行 实例 黑色/深色表格 实例 黑色/深色条纹表格 实例 可悬停的黑色/深色表格 实例 无边框表格 实例 上下文类 可用的上下文类: 实例 表头颜色 实例 小型表格 实例 响应…...

喜报 | 再度中标南网项目!AR 开启电力远程运维新智慧
近日,中国南方电网官网发布《2023年南方电网数字平台科技 (广东)有限公司物资品控远程协助软件采购项目中标公告》,ALVA Systems 凭借 ALVA Rainbow 创新应用竞得此标。 随着相关技术的逐步成熟,基础问题远程化解决已经在工业领域广泛应用。 …...

3.使用IDE的优点
IDE是集成开发环境:Integrated Development Environment的缩写。 1、优点 使用IDE的好处在于,可以把编写代码、组织项目、编译、运行、调试等放到一个环境中运行,能极大地提高开发效率。 IDE提升开发效率主要靠以下几点: 编辑器…...

ShopXO商城系统文件上传0Day代审历程
Git仓库: https://github.com/gongfuxiang/shopxo简介: 两天攻防中,某政局内网横向发现多网段服务器,该服务器搭建了ShopXO商城系统(后来发现是开发临时搭建的,准备做二开用的)。结果花了30来秒审了个垃圾Day拿下该服…...

【java】【项目实战】[外卖十二]【完结】项目优化(前后端分离开发)
目录 一、问题说明 二、前后端分离开发 1、介绍 2、开发流程 3、前端技术栈 三、Yapi 1、介绍 2、部署 3、使用 3.1 添加项目编辑 3.2 添加分类编辑 3.3 添加接口 3.4 运行 3.5 导出接口 3.6 导入数据 四、Swagger 1、介绍 2、使用方式 2.1 pom 2.2 导入…...

解决uniapp下拉框 内容被覆盖的问题
1. 下拉框 内容被覆盖的问题 场景: 现在是下拉框被表格覆盖了 解决办法: 在表格上添加css 样式来解决这个问题 .add-table{display: static;overflow: visible; } display: static: 将元素会按照默认的布局方式进行显示,不会分为块状或行内元素。 overflow: vi…...

论文解读 | KPConv——点云上的可形变卷积网络
原创 | 文 BFT机器人 《KPConv: Flexible and Deformable Convolution for Point Clouds》是一篇发表于2019年的研究论文,作者为Hugues Thomas、Charles R. Qi、Jean-Emmanuel Deschaud、Beatriz Marcotegui和Franois Goulette。这篇论文关注于点云数据上的卷积操作…...

STM32 物联网 4G CAT1 SIMCOM A7680C 源码
基于状态机编写4G模块驱动函数 #include "bsp.h" char LTE_TX[512],LTE_RX[512]; int LTE_TX_length,LTE_RX_length; char U1_TX_data[512],U1_RX_data[512]; char LTE_DATA_buf[512]; char LTE_COM_buf[512]; char LTE_SEND_buf[512];unsigned char U1_TX_flag,U1…...

ETLCloud制造业轻量级数据中台解决方案
制造业数据处理特点 制造业在业务发展过程中产生大量的业务交易数据以及设备运行过程中的状态数据,但是制造业有别于其他互联网或零售行业,其数据处理具有以下特点: 数据量不大,大部分业务系统的数据库表在1000W以下数据结构复杂…...

解决外接显示器后Edge浏览器地址栏等变得很大的问题
解决外接显示器后Edge浏览器地址栏等变得很大的问题 edge设置里外观——触控模式,把触控模式关了...

k8s 启动和删除pod
k8s创建pod pod的启动流程 流程图 运维人员向kube-apiserver发出指令(我想干什么,我期望事情是什么状态) api响应命令,通过一系列认证授权,把pod数据存储到etcd,创建deployment资源并初始化。(期望状态) controller通过list-wa…...

Jenkins详解(三)
Jenkins详解(三) 目录 Jenkins详解(三) 1、Jenkins介绍2、Jenkins CI/CD 流程3、部署环境 3.1 环境准备3.2 安装GitLab3.3 初始化GitLab3.4 GitLab中文社区版补丁包安装3.5 修改GitLab配置文件/etc/gitlab/gitlab.rb3.6 在宿主机输入 http://192.168.200.26:88 地址就可以访问了…...

【真题解析】系统集成项目管理工程师 2023 年上半年真题卷(综合知识)
本文为系统集成项目管理工程师考试(软考) 2023 年上半年真题(全国卷),包含答案与详细解析。考试共分为两科,成绩均 ≥45 即可通过考试: 综合知识(选择题 75 道,75分)案例分析(问答题 4 道,75分)综合知识(选择题*75)1-10 题11-20 题21-30 题31-40 题41-50 题51-60 …...

开始MySQL之路——MySQL存储引擎概念
一、存储引擎概念 MySQL数据库和大多数的数据库不同, MySQL数据库中有一个存储引擎的概念, 针对不同的存储需求可以选择最优的存储引擎。 存储引擎就是存储数据,建立索引,更新查询数据等等技术的实现方式 。存储引擎是基于表的,而不是基…...

ant-design 设置Form.Item中的input框的值的方法
ant-design 设置Form.Item中的input中的value值是不知道什么原因是无效的,所以有以下两种方法设置: 1.可以通过 initialValues 属性来为表单设置默认值。具体使用方法如下: 在表单最外层的 Form 组件上加入 initialValues 属性,…...