【pytest学习总结2.3】 - 如何使用固定装置fixtures(2)

news2024/9/27 23:23:35

目录

2.3.8 使用mark给固定装置传递数据

2.3.9 将固定装置工厂化

2.3.10 参数化固定装置

2.3.11 使用带有参数化固定装置的标记

2.3.12 使用来自固定装置功能中的固定装置 - 模块化

2.3.13 按固定装置实例自动分组测试

2.3.14 在类和模块中使用usefixtures

2.3.15 固定装置覆盖在不同级别上

2.3.16 使用从其他项目中获得的固定装置

🎁更多干货

完整版文档下载方式:


2.3.8 使用mark给固定装置传递数据

使用请求对象,夹具还可以访问应用于测试功能的标记。这对于将测试中的数据传递到夹具中非常有用:

import pytest


@pytest.fixture()
def fixt(request):
    marker = request.node.get_closest_marker("fixt_data")
    if marker is None:
        # Handle missing marker in some way...
        data = None
    else:
        data = marker.args[0]
    # Do something with the data
    return data


@pytest.mark.fixt_data(42)
def test_fixt(fixt):
    assert fixt == 42

2.3.9 将固定装置工厂化

“工厂即夹具”模式可以在一次测试中需要多次获得夹具结果的情况下提供帮助。固定装置不是直接返回数据,而是返回一个生成数据的函数。这个函数可以在测试中多次调用

import pytest

@pytest.fixture
def make_customer_record():
	def _make_customer_record(name):
		return {"name": name, "orders": []}
	return _make_customer_record

def test_customer_records(make_customer_record):
	customer_1 = make_customer_record("Lisa")
	customer_2 = make_customer_record("Mike")
	customer_3 = make_customer_record("Meredith")
	print(customer_1, customer_2, customer_3)

如果工厂函数创建的数据需要管理,那么设备可以处理这些问题:

import pytest

@pytest.fixture
def make_customer_record():
	created_records = []
	def _make_customer_record(name):
		record = models.Customer(name=name, orders=[])
		created_records.append(record)
		return record
	yield _make_customer_record
	for record in created_records:
		record.destroy()

def test_customer_records(make_customer_record):
	customer_1 = make_customer_record("Lisa")
	customer_2 = make_customer_record("Mike")
	customer_3 = make_customer_record("Meredith")
	print(customer_1, customer_2, customer_3)

2.3.10 参数化固定装置

夹具函数可以参数化,在这种情况下,它们将被调用多次,每次执行一组依赖的测试时,即依赖于此固定装置的测试。测试函数通常不需要知道它们的重新运行,夹具参数化有助于为组件编写详尽的功能测试,这些组件本身可以以多种方式进行配置。
数字、字符串、布尔值和None将在测试ID中使用它们通常的字符串表示形式,对于其他对象,pytest将根据参数名称创建一个字符串。可以使用id关键字参数自定义特定固定值的测试ID中使用的字符串:
上面显示了id如何可以是一个要使用的字符串列表,或者是一个将用固定装置值调用的函数,然后必须返回一个要使用的字符串。在后一种情况下,如果函数返回None,那么将使用pytest的自动生成的ID。

import pytest

@pytest.fixture(params=[0,1], ids=["spam", "ham"])
def a(request):
    return request.param

def test_a(a):
    pass

def idfn(fixture_value):
    if fixture_value == 0:
        return "eggs"
    else:
        return None

@pytest.fixture(params=[0, 1], ids=idfn)
def b(request):
    return request.param

def test_b(b):
    pass

C:\Users\mc\Desktop\python基础>pytest test_ids.py -vs
================================== test session starts ==================================
platform win32 -- Python 3.9.6, pytest-7.1.1, pluggy-0.13.1 -- c:\python39\python.exe
cachedir: .pytest_cache
rootdir: C:\Users\mc\Desktop\python基础
collected 4 items                                                                        
test_ids.py::test_a[spam] PASSED
test_ids.py::test_a[ham] PASSED
test_ids.py::test_b[eggs] PASSED
test_ids.py::test_b[1] PASSED
=================================== 4 passed in 0.02s ===================================

2.3.11 使用带有参数化固定装置的标记

# content of test_fixture_marks.py
import pytest
@pytest.fixture(params=[0, 1, pytest.param(2, marks=pytest.mark.skip)])
def data_set(request):
    return request.param
def test_data(data_set):
    pass

pytest.param()可以用于在参数化装置的值集中应用标记,就与@pytest.mark.parametrize使用一样。

collected 3 items                                                                        
test_fixture_marks.py::test_data[0] PASSED
test_fixture_marks.py::test_data[1] PASSED
test_fixture_marks.py::test_data[2] SKIPPED (unconditional skip)

2.3.12 使用来自固定装置功能中的固定装置 - 模块化

除了在测试功能中使用固定装置外,装置功能还可以使用其他装置本身。这有助于实现设备的模块化设计,并允许在许多项目中重用特定于框架的设备。作为一个简单的示例,我们可以扩展前面的示例,并实例化一个对象应用程序,其中我们将已经定义的smtp_connection资源插入其中:

# content of test_appsetup.py
import pytest
class App:
    def __init__(self, smtp_connection):
        self.smtp_connection = smtp_connection
        
@pytest.fixture(scope="module")
def app(smtp_connection):
    return App(smtp_connection)

def test_smtp_connection_exists(app):
    assert app.smtp_connection

2.3.13 按固定装置实例自动分组测试

在测试过程中最小化活动装置的数量。如果您有一个参数化的装置,那么使用它的所有测试将首先使用一个实例执行,然后在创建下一个固定实例之前调用终结器。除此之外,这还简化了对创建和使用全局状态的应用程序的测试。
下面的示例使用两个参数化的固定装置,其中一个是基于每个模块的范围,所有函数都执行打印调用以显示设置/拆卸流程:

# content of test_module.py
import pytest

@pytest.fixture(scope="module", params=["mod1", "mod2"])
def modarg(request):
    param = request.param
    print(" SETUP modarg", param)
    yield param
    print(" TEARDOWN modarg", param)

@pytest.fixture(scope="function", params=[1, 2])
def otherarg(request):
    param = request.param
    print(" SETUP otherarg", param)
    yield param
    print(" TEARDOWN otherarg", param)

def test_0(otherarg):
    print(" RUN test0 with otherarg", otherarg)
def test_1(modarg):
    print(" RUN test1 with modarg", modarg)
def test_2(otherarg, modarg):
    print(f" RUN test2 with otherarg {otherarg} and modarg {modarg}")

特别注意,test_0是完全独立的,首先完成。然后用mod1执行test_1,然后用mod1执行test_2,然后用mod2执行test_1,最后用mod2执行test_2

C:\Users\mc\Desktop\python基础>pytest test_module.py -vs
================================== test session starts ==================================
platform win32 -- Python 3.9.6, pytest-7.1.1, pluggy-0.13.1 -- c:\python39\python.exe
cachedir: .pytest_cache
rootdir: C:\Users\mc\Desktop\python基础
collected 8 items                                                                        

test_module.py::test_0[1]  SETUP otherarg 1
 RUN test0 with otherarg 1
PASSED TEARDOWN otherarg 1

test_module.py::test_0[2]  SETUP otherarg 2
 RUN test0 with otherarg 2
PASSED TEARDOWN otherarg 2

test_module.py::test_1[mod1]  SETUP modarg mod1
 RUN test1 with modarg mod1
PASSED
test_module.py::test_2[mod1-1]  SETUP otherarg 1
 RUN test2 with otherarg 1 and modarg mod1
PASSED TEARDOWN otherarg 1

test_module.py::test_2[mod1-2]  SETUP otherarg 2
 RUN test2 with otherarg 2 and modarg mod1
PASSED TEARDOWN otherarg 2

test_module.py::test_1[mod2]  TEARDOWN modarg mod1
 SETUP modarg mod2
 RUN test1 with modarg mod2
PASSED
test_module.py::test_2[mod2-1]  SETUP otherarg 1
 RUN test2 with otherarg 1 and modarg mod2
PASSED TEARDOWN otherarg 1

test_module.py::test_2[mod2-2]  SETUP otherarg 2
 RUN test2 with otherarg 2 and modarg mod2
PASSED TEARDOWN otherarg 2
 TEARDOWN modarg mod2
=================================== 8 passed in 0.05s ===================================

2.3.14 在类和模块中使用usefixtures

有时,测试函数并不需要直接访问夹具对象。例如,测试可能需要使用一个空目录作为当前工作目录进行操作,否则就不关心具体目录。下面是你如何使用标准的诱惑文件和最糟糕的固定装置来实现它。我们将该设备的创建分离成一个conftest.py文件:

# content of conftest.py
import os
import tempfile
import pytest

@pytest.fixture
def cleandir():
    with tempfile.TemporaryDirectory() as newpath:
        old_cwd = os.getcwd()
        os.chdir(newpath)
        yield
        os.chdir(old_cwd)

# content of test_setenv.py
import os
import pytest


@pytest.mark.usefixtures("cleandir")
class TestDirectoryInit:
    def test_cwd_starts_empty(self):
        assert os.listdir(os.getcwd()) == []
        with open("myfile", "w") as f:
            f.write("hello")
    def test_cwd_again_starts_empty(self):
        assert os.listdir(os.getcwd()) == []

由于使用装置标记,执行每个测试方法都需要清理dir夹,就像您为每个测试方法指定了一个“清理dir”函数参数一样。让我们运行它来验证我们的固定装置是否被激活,并且测试是否通过:

C:\Users\mc\Desktop\python基础>pytest -q test_setenv.py
..                                                                                 [100%]
2 passed in 0.02s

您可以像这样指定多个固定装置:

@pytest.mark.usefixtures("cleandir", "anotherfixture")
def test():
	...

您可以使用测试标记在测试模块级别指定固定装置的使用:

pytestmark = pytest.mark.usefixtures("cleandir")

也可以将项目中所有测试所需的固定装置放入一个ini文件中:

# content of pytest.ini
[pytest]
usefixtures = cleandir

2.3.15 固定装置覆盖在不同级别上

在相对较大的测试套件中,您很可能需要使用本地定义的设备覆盖全局或根设备,以保持测试代码的可读性和可维护性。

  1. 覆盖文件夹(conftest)级别
tests/
	__init__.py
	conftest.py
		# content of tests/conftest.py
		import pytest
		
		@pytest.fixture
		def username():
		return 'username'
	test_something.py
		# content of tests/test_something.py
		def test_username(username):
		assert username == 'username'
subfolder/
	__init__.py
	conftest.py
		# content of tests/subfolder/conftest.py
		import pytest
		@pytest.fixture
		def username(username):
		return 'overridden-' + username
	test_something.py
		# content of tests/subfolder/test_something.py
		def test_username(username):
		assert username == 'overridden-username'

  1. 用直接的测试参数化来覆盖一个固定装置 在上面的示例中,夹具值会被测试参数值覆盖。请注意,即使测试没有直接使用它(在函数原型中没有提到它)
tests/
	__init__.py
	conftest.py
		# content of tests/conftest.py
		import pytest
		@pytest.fixture
		def username():
			return 'username'
		@pytest.fixture
		def other_username(username):
			return 'other-' + username
	test_something.py
		# content of tests/test_something.py
		import pytest
		@pytest.mark.parametrize('username', ['directly-overridden-username'])
		def test_username(username):
			assert username == 'directly-overridden-username'
		@pytest.mark.parametrize('username', ['directly-overridden-username-other'])
		def test_username_other(other_username):
			assert other_username == 'other-directly-overridden-username-other'

  1. 用非参数化的装置覆盖参数化的装置,反之亦然
tests/
	__init__.py
	conftest.py
		# content of tests/conftest.py
		import pytest
		@pytest.fixture(params=['one', 'two', 'three'])
		def parametrized_username(request):
			return request.param
		@pytest.fixture
		def non_parametrized_username(request):
			return 'username'
	test_something.py
		# content of tests/test_something.py
		import pytest
		@pytest.fixture
		def parametrized_username():
			return 'overridden-username'
		@pytest.fixture(params=['one', 'two', 'three'])
		def non_parametrized_username(request):
			return request.param
		def test_username(parametrized_username):
			assert parametrized_username == 'overridden-username'
		def test_parametrized_username(non_parametrized_username):
			assert non_parametrized_username in ['one', 'two', 'three']
	test_something_else.py
		# content of tests/test_something_else.py
		def test_username(parametrized_username):
			assert parametrized_username in ['one', 'two', 'three']
		def test_username(non_parametrized_username):
			assert non_parametrized_username == 'username'

在上面的例子中,参数化的装置被非参数化版本覆盖,而非参数化的装置被特定测试模块的参数化版本覆盖。显然,这也同样适用于测试文件夹级别。

2.3.16 使用从其他项目中获得的固定装置

假设你在我的库中有一些固定装置。固定装置,你想将它们重用到你的应用程序/测试目录中。您所需要做的就是在app/tests/conftest.py中定义指向该模块的pytest_plugins

pytest_plugins = "mylibrary.fixtures"

这有效地注册了我的程序库。固定装置作为一个插件,使它的所有固定装置和钩子都可以在应用程序/测试中进行测试

🎁更多干货


完整版文档下载方式:

这些资料,对于从事【软件测试】等相关工作的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴我走过了最艰难的路程,希望也能帮助到你!以上均可以分享。

在评论区和我互动交流或者私❤我【软件测试学习】领取即可,拿走不谢。


如果我的博客对你有帮助、如果你喜欢我的博客内容,请 “👍点赞” “✍️评论” “💙收藏” 一键三连哦!

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

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

相关文章

四.安防摄像机的WDR(HDR) 性能

四.安防摄像机的WDR(HDR) 性能 4.0 概述 WDR就是宽动态,wide dynamic range,或者HDR,high dynamic range,本质上是一回事,没任何区别。那么,到底什么是宽呢?很简单,搞不定的,就是太宽了,比如 摄像机装在室内,室内正常照度500lux,玻璃门外就是10000lux,室内外…

单机取证-鉴于信息安全管理与评估赛项-计算机单机取证特别说明-例题详解-Autopsy使用

芜湖~ 本期针对全国职业技能大赛-信息安全管理与评估赛项分析一下单机取证这个大项 并且取一例题 进行例题讲解 分享一些思路和逻辑 目录 题目 前言分析 .E01 ⽂件 DD 镜像和 E01 镜像的主要区别 如何打开和查看 E01 ⽂件扩展名? 常用工具使用-Autopsy 正…

现在这个年代,还有必要进行JVM调优吗?

导言 随着技术的不断发展,软件开发行业也在日新月异地进步。在过去的几十年里,Java语言和Java虚拟机(JVM)在开发企业级应用方面扮演了重要角色。然而,随着硬件和软件的进步,以及JVM本身的改进,…

Linux驱动学习(4) MTD字符驱动和块驱动1

系列文章目录 Linux驱动学习(4) 文章目录 目录 目录 系列文章目录 文章目录 前言 一、MTD是什么? 二、MTD子系统架构 1.Linux文件存储基本架构: ​ 2.MTD子系统基本架构: 总结 前言 MTD设备在嵌入式设备中…

2023网安面试题164道(附答案)

最近有不少小伙伴跑来咨询: 想找网络安全工作,应该要怎么进行技术面试准备?工作不到 2 年,想跳槽看下机会,有没有相关的面试题呢? 为了更好地帮助大家高薪就业,今天就给大家分享两份网络安全工…

【pytest学习总结2.2 】- 如何在测试中编写断言?

目录 2.2 如何在测试中编写断言 2.2.1 assert 断言 2.2.2 断言预期的异常 2.2.3 断言预期警告 【后续内容更新】 2.2.4 断言上下文 2.2.5 为失败的断言定义您自己的解释 2.2.6 断言的详细内容 🎁更多干货 完整版文档下载方式: 2.2 如何在测试中…

C++ 哈希思想 unordered_set unordered_map

文章目录 哈希思想常用的哈希函数哈希冲突解决方案哈希代码实现(C 源码)unordered_set & unordered_map 容器**unordered_set & unordered_map模拟实现**(C 源码) 哈希思想 抽象感受哈希的优点 如果我现在抛出一个问题&a…

Python+OpenCV 实现图像位平面分层进行图像信息隐藏

引言 闲言:这篇博客回归了传统图像处理领域,主要是在研究生的数字图像处理课程上接触到了新的知识–图像位平面,觉得还挺有意思的,可以用来做信息隐藏,索性记录一下。因为拖延的缘故,到学期末才赶出来一篇&…

计算机毕业论文内容参考|基于Android的旅游攻略APP的设计与实现

文章目录 导文摘要:前言:绪论:1. 课题背景:2. 国内外现状与趋势:3. 课题内容:相关技术与方法介绍:系统分析:系统设计:系统实现系统测试总结与展望本文总结后续工作展望导文 计算机毕业论文内容参考|基于Android的旅游攻略APP的设计与实现 摘要: 本文基于Android平台…

python单元测试框架Unittest详解

前言 我们今天来聊聊Python中的单元测试框架unittest,大家都知道在Python中比较热门的测试框架除了pytest就是unittest,我之前有讲过pytest所以今天想讲unittest。喜欢的可以点点关注哟。 Unittest详解 Unittest是Python内部自带的一个单元测试的模块&…

mysql——初步认识

数据库是什么? 数据库(Database)是按照数据结构来组织、存储和管理数据的仓库 说人话 就是 数据库是一个电子仓库,里面存了一些数据 我们要学习的mysql就是数据库中的一种,并且是一种关系型数据库,当然有…

ASEMI快恢复二极管MUR20100DCR的性能与应用

编辑-Z 本文主要介绍了MUR20100DCR二极管的性能与应用。我们将对MUR20100DCR二极管的基本性能、不同领域的应用和优势与不足进行分析。 1、MUR20100DCR二极管的基本性能 MUR20100DCR二极管是一种高性能的超快速二极管,具有高电压、高电流和低漏电流等特点。它采用…

基于Python所写的企业编码生成系统

点击以下链接获取源码资源: https://download.csdn.net/download/qq_64505944/87950401?spm1001.2014.3001.5503 在PyCharm中运行《企业编码生成系统》即可进入如图1所示的系统主界面。在该界面中可以选择要使用功能对应的菜单进行不同的操作。在选择功能菜单时&…

那些曾经考过的turtle绘图题(11~15)

【编程实现绘图 -11】 利用random库和turtle库,在屏幕上绘制4个小雪花,雪花半径随机,坐标由列表points给出,雪花颜色为红色,效果如图所示 points = [[0,0], [50, 40], [70, 80], [-40, 30]] # 样例代码 from turtle import * # 导入turtle库 import random pensize(4) …

【深入探讨】区块链的历史与现状

发表时间:2023年5月18日 最近,BSV比特币协会在德克萨斯州奥斯汀举办了首届Unbound Perspectives Live Summit活动。本次活动采取非公开形式,大约有100人受邀参会。 与会者包括了Unbounded Capital公司的有限合伙人、知名风险投资和对冲基金经…

跳跃表详解

跳跃表[SkipList]是一种基于有序链表的扩展,简称跳表,其就是使用关键节点作为索引的一种数据结构 怎样能更快查找到一个【有序链表】的某一节点呢? 可以利用类似【索引】的思想,提取出【链表】中的【部分关键节点】 比如&#…

bean的实例化和初始化

Instantiation:表示实例化,对象还未生成 Initialization:表示初始化,对象已经生成 InstantiationAwareBeanPostProcessor继承自BeanPostProcessor,它内部提供了3个方法,再加上BeanPostProcessor接口内部的2个方法,所…

VS Code 安装

前端开发工具 VSCodeHBuildersublimeWebStorm VS Code 一、介绍 Visual Studio Code(简称 VS Code )是 Microsoft 于2015年4月发布的一款代码编辑器。VS Code 对前端代码有非常强大的支持,同时也其他编程语言(例如&#xff1a…

20年运维老兵,SRE领域大咖张观石揭秘FinOps体系实践方法

当前,降本增效成为各大互联网公司的重要方向,IT成本则占据了互联网成本的大头。随着IT资源成本花费越来越高,很多公司意识到掌握管控成本和优化成本的重要性。 如何有效的降本?如何做好成本的洞察管控?如何掌握资源成…

ECDH 算法

一、简介 ECDH全称是椭圆曲线迪菲-赫尔曼秘钥交换(Elliptic Curve Diffie–Hellman key Exchange),主要是用来在一个不安全的通道中建立起安全的共有加密资料,一般来说交换的都是私钥,这个密钥一般作为“对称加密”的…