pytest自动化测试框架tep环境变量、fixtures、用例三者之间的关系

news2024/11/23 12:34:21

 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 request

def 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固定,假如需要切换两个环境qarelease,该怎么办?

参数化

无论是做自动化测试还是性能测试,都会接触到参数化这个词。它是指把代码中的固定数据(硬编码)定义成变量,让每次运行时数据不一样,固定数据变为动态数据。动态数据的来源是变量、数据库、外部文件等。动态数据的类型一般是常量的字符串,也可以是函数,比如JMeter的函数助手,也可以是依赖注入,比如pytest的fixture。

依赖注入的fixture

“依赖注入是控制反转(IoC, Inversion of Control)的一种技术形式”,这句话出自维基百科,我也不知道什么意思,画个图简单表达下:

意思是,给client一个injectorclient不需要做什么,就能用到service

pytest的fixture实现了依赖注入,允许我们在不修改测试代码的情况下,引入fixture来额外添加一些东东。

对于url来说,域名是需要做参数化的,不同环境域名不同,所以tep把它做成了fixture,通过函数参数引入:

from tep.client import request
from tep.fixture import *

def test(url):  # 引入fixture
    response = 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 = "/" + uri
        return env_vars.domain + uri

    return 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"了。

既然是变量,那么就能随便赋值,strfunctionclassobject都行。比如在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 = "/" + uri
        return env_vars.domain + uri

    return 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 = None
    return func

第二步:

@pytest.fixture(scope="session")
def url(env_vars):
    func = None
    
    
    def domain_and_uri(uri):
        if not uri.startswith("/"):
            uri = "/" + uri
        return env_vars.domain + uri

    
    func = domain_and_uri
    return 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 variables
        mapping = {
            "qa": {
                "domain": "https://qa.com",
            },
            "release": {
                "domain": "https://release.com",
            }
            # Add your environment and variables
        }
        # Define properties for auto display
        domain = 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 variables
        mapping = {
            "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 display
        domain = mapping[env]["domain"]
        domain_school = mapping[env]["domain_school"]  # 新增
        domain_org = mapping[env]["domain_org"]  # 新增
        """Variables define end"""

添加了6行代码,定义了env_vars.domain_schoolenv_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 = "/" + uri
        return env_vars.domain_school + uri

    return domain_and_uri
    

@pytest.fixture(scope="session")
def url_org(env_vars):
    def domain_and_uri(uri):
        if not uri.startswith("/"):
            uri = "/" + uri
        return env_vars.domain_org + uri

    return domain_and_uri

参照tep.fixture.url,修改env_vars.domainenv_vars.domain_schoolenv_vars.domain_org,新增了2个fixture url_schoolurl_org

更进一步,也许会定义fixture login_schoollogin_org,灵活选择。

小结

本文循序渐进的讲解了tep环境变量、fixtures和用例之间的关系,重点对tep.fixture.url进行了解释,只要理解了它,整体关系就很清楚了。之所以要用fixture,原因一是多人协作共享,我们需要用别人写好的函数,复用返回值,有些同学习惯定义函数参数,参数不变还好,万一哪天改了,别人引用的用例会全部报错,fixture很好的限制了这一点,它默认是不能传参的,虽然可以通过定义内部函数来实现传参,但是并不推荐这么做,宁愿增加冗余代码,定义多个fixture,也比代码耦合度高好一些。原因二是import的问题,pytest会自动查找conftest.py里的fixture,tep会进一步自动查找fixtures下的fixture导入到conftest.py,不需要import就能使用,减少了import代码,避免了可能会出现的循环导入问题。

正在学习测试的小伙伴可以通过点击下面的小卡片

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

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

相关文章

低代码治好了CIO们的 “精神内耗”

目录 一、前言 二、低代码在企业数字化转型中能“C位出道”&#xff0c;凭什么&#xff1f; 三、低代码的数字化构建能力 四、结束语 一、前言 近两年&#xff0c;我发现身边的CIO/CTO朋友都得了一种“病”——“数字化焦虑”症。 他们经常皱着眉头问我&#xff1a;“老板对数字…

gradio初体验

背景 近期随着很多开源大模型的出现&#xff0c;对于其如何落地&#xff0c;或者说充分地去挖掘其实际应用领域和商业价值变得格外重要。于是乎&#xff0c;对于不懂技术的前方市场或销售人员&#xff0c;如何在没有形成AI产品之前向其展示算法模型效果呢&#xff1f;这时候gr…

【严重】Citrix ADC 和 Citrix Gateway 远程代码执行漏洞(PoC)

漏洞描述 Citrix ADC是应用程序交付和负载平衡解决方案&#xff0c;Citrix Gateway是一套安全的远程接入解决方案&#xff0c;常用于提供虚拟桌面和远程桌面服务&#xff0c;此外&#xff0c;Citrix ADC还被广泛用作Windows堡垒机。 在 Citrix ADC 和 Citrix Gateway 受影响版…

《我为什么要听你的 如何与强势的人相处》读书笔记二

目录 反驳例子 勇敢反击的益处 一些重要的自我保护法 不要再讲述你生活中的细节 别答应那些表意不明的请求 记录下一切 第一时间告知亲友 拒绝成为中间人 区别对待强势者 谨慎应对奉承话 想方设法快点跑 反驳例子 例子 例子&#xff1a; 例子&#xff1a; 例子&am…

什么是UE像素流送,像素流推流是什么原理?

游戏开发者通常在运行游戏逻辑时会将游戏渲染到屏幕的同一台设备上来运行虚幻引擎应用&#xff0c;多人联网游戏可能会在应用程序的多个实例之间分发部分游戏逻辑&#xff0c;但每个单独的实例仍然会为自己的玩家在本地渲染游戏。即使是使用 HTML5 部署选项创建可以在 Web 浏览…

CountDownLatch 一个神奇的计数器,您了解吗

一、CountDownLatch基础概念及案例 1.CountDownLatch是java.util.concurrent 包下提供一个同步工具类&#xff0c;它允许一个或多个线程一直等待&#xff0c;直到其他线程执行完成再执行。其本质就是一个计数器&#xff0c;传入一个初始的值&#xff0c;调用await 方法会阻塞当…

vue+Element项目中v-for循环+表单验证

如果在Form 表单里有通过v-for动态生成&#xff0c;如何设置验证呢&#xff1f; <el-form ref"ruleFormRef" :model"ruleForm" status-icon :rules"rules" label-width"120px"class"demo-ruleForm" hide-required-aster…

大数据课程综合实验案例---课设问题汇总

最近翻看两年前的大数据课设&#xff0c;感觉这个大数据课设实验当时答辩 在大数据课设实验过程中&#xff0c;我遇到了很多问题&#xff0c;在这里做出汇总&#xff1a; 1、MySQL启动报错 首先&#xff0c;我的MySQL有时候启动不了&#xff0c;当我输入这个命令的时候&#…

ModuleNotFoundError: No module named sklearn

前言 出现ModuleNotFoundError: No module named sklearn’的debug过程记录 步骤 安装机器学习库&#xff0c;需要注意报错的sklearn是scikit-learn缩写。 pip install scikit-learn 完成&#xff0c;不再报错

剖析Linuxptp中ptp4l实现--OC

源码克隆地址&#xff1a; git://git.code.sf.net/p/linuxptp/code 项目官网文档&#xff1a; https://linuxptp.nwtime.org/documentation/ 关于linuxptp的相关配置可以参考以下博文&#xff1a; linuxptp/ptp4l PTP时钟同步配置选项 代码剖析 ptp4l的main函数在ptp4l.…

“学习嵌入式开发:明确目标,提升技能“

嵌入式领域涵盖广泛&#xff0c;不可能一次性掌握所有知识。因此&#xff0c;明确学习目标和方向非常重要。选择感兴趣且与职业发展相关的领域进行深入学习是明智之举。 嵌入式技术在不断发展&#xff0c;过去与现在存在差异。选择学习当前行业的主流技术和趋势是明智选择。掌…

基于STM32设计的人体健康监护系统(华为云IOT)

一、设计需求 1.1 设计需求总结 根据需求,要求设计一款基于 STM32 的人体健康监护系统。采用系统模块化思路进行,将多个数模传感器收集到的数据和操作指令一并送至 STM32 中心处理器进行处理分析。 该系统可以实时监测被测者的心率、体温以及周围环境的温度,也同时可以通…

生物信息学_玉泉路_课堂笔记_06 第六章 基因组学:遗传变异分析以及FGWAS

&#x1f345; 课程&#xff1a;生物信息学_玉泉路_课堂笔记 中科院_2022秋季课 第一学期 &#x1f345; 个人笔记使用 &#x1f345; 2023/7/21 课程回顾 第六章 基因组学&#xff1a;遗传变异分析以及FGWAS 第一节 SNP 与 Indel 的鉴定与分析 基本概念 参考基因组 和基因组…

tinkerCAD案例:9.Twist Earrings 扭耳环

tinkerCAD案例&#xff1a;9.Twist Earrings 扭耳环 In this lesson you learn how to create earrings by using cylinder shapes. Let’s get started! 在本课中&#xff0c;您将学习如何使用圆柱形制作耳环。让我们开始吧&#xff01; 说明 Drag a Cylinder shape to the w…

为Android构建现代应用—— 练习状态管理

介绍 本章是一个应用上一章&#xff1a;设计原则中学到的概念的项目。 项目的目标包括以下实现&#xff1a; • 创建一个应用程序&#xff0c;该应用程序使用View作为真实来源。 • 修改应用程序&#xff0c;使其使用ViewModel作为真实来源。 • 将状态和事件进行分组&#x…

N型光伏电池技术“两头开花”,谁是诗和远方?

光伏产业已经进入大规模、市场化发展的新阶段。 近日&#xff0c;国家能源局公布了上半年全国电力工业统计数据&#xff0c;根据总装机容量&#xff0c;光伏装机已正式成为我国第二大电源装机&#xff0c;仅次于煤电。 作为新兴产业&#xff0c;光伏市场持续扩容总是伴随着技…

SpringMVC----(1)基础

SringMVC 1 SpringMVC简介2 SpringMVC入门案例2.1 入门案例2.2 入门案例工作流程2.3 bean加载控制2.4 PostMan工具 3 请求与响应3.1 请求映射路径3.2 Get和Post请求发送普通参数3.3 请求头的五种类型参数传递3.4 请求体的JSON数据传输参数3.5 日期型参数3.6 响应 4 REST风格4.1…

SpringCloud整合Nacos配置中心

&#x1f4dd; 学技术、更要掌握学习的方法&#xff0c;一起学习&#xff0c;让进步发生 &#x1f469;&#x1f3fb; 作者&#xff1a;一只IT攻城狮 &#xff0c;关注我&#xff0c;不迷路 。 &#x1f490;学习建议&#xff1a;1、养成习惯&#xff0c;学习java的任何一个技术…

NoSQL之Redis配置使用

目录 一、关系数据库与非关系型数据库 1.1.关系型数据库的概述 1.2关系型数据库的优缺点 1.2.1优点 1.2.2缺点 1.3.非关系型数据库的概述 二.关系数据库与非关系型数据库的区别 2.1数据存储方式不同 2.2扩展方式不同 2.3对事务性的支持不同 2.4非关系型数据库产生背景 2…

亚马逊攀岩绳EN892:2012+A1:2016安全带标准、攀岩安全带EN 12277:2015登山装备要求和ASTM F1772–17体育运动安全标准规范

如果您在亚马逊商城发布商品&#xff0c;则必须遵守适用于这些商品和商品信息的所有联邦、州和地方法律以及亚马逊政策&#xff08;包括本政策&#xff09;。 本政策适用的攀岩安全带 本政策适用于主要在攀岩或登山期间使用且使用者双脚不接触地面时使用的安全带。安全带是一种…