• 【pytest官方文档】解读- 如何自定义mark标记,并将测试用例的数据传递给fixture函数


    在之前的分享中,我们知道可以使用yield或者return关键字把fixture函数里的值传递给test函数

    这种方法很实用,比如我在fixture函数里向数据库里插入必要的测试数据,那我就可以把相关数据返回给test函数用来做相关断言查询等操作。

    那如果我想把test函数(也就是测试用例)中的数据传给fixture函数使用,要如何实现呢?

    直接先贴上一段示例代码:

    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个知识点,可能有的小伙伴并不熟悉,分别来看下。

    1. Mark 标记

    什么是mark标记,干什么用?

    标记可以将元数据应用于测试函数(注意,不能是fixture函数),后续可以通过fixture函数或者plugins插件进行访问。

    框架有一些内置的marks,也可以支持我们自定义

    内置的在之前的系列分享中有出现过几个,比如:

    • pytest.mark.parametrize:参数化
    • pytest.mark.skip:跳过测试用例
    • pytest.mark.skipif: 根据条件跳过用例

    其他就不展开了,上述提到的分享文章链接会附在文末。

    而在上述示例代码中,pytest.mark.fixt_data则是属于自定义的mark标记,fixt_data我也可以改成fixt_pingguo也是可以的。

    2. request

    request本身也是一个fixture函数,但是很特殊,用于提供当前正在执行请求的上下文信息。

    在上述示例代码中,测试函数test_fixt请求了fixture函数fixt,那么在这次请求中相关联到的信息就可以在request中获得。
    比如:

    • fixturename: 当前这个fixture函数的名称
    • module: 当前测试函数所在的模块
    • scope:当前fixture函数作用范围
    • node:基于当前测试范围搜集到的底层节点对象,这里又包含了很多信息。
      ...

    就不一一展开了,有兴趣的童鞋可以在编辑器里打个断点,查看对应的信息详情。

    二、通过自定义mark传递数据

    回到示例代码,我们可以先直接执行一下代码。

    测试是通过的(warning先忽略,因为没有注册自定义的mark),也就是说@pytest.mark.fixt_data(42)中的42是成功的带到了fixture函数中,经过函数中的处理后最后返回出来。

    其中的get_closest_marker("fixt_data")方法,是返回与名称fixt_data匹配的第一个mark,从最近的级别到更远的级别,比如从函数到模块级别。

    所以在这里,被找到的mark就是我们自定义的这个@pytest.mark.fixt_data(42)标记了。

    1. 自定义mark知识点

    标记是使用工厂对象pytest.mark动态创建的,用于装饰器,所以我们可以用语法糖@直接使用即可。

    mark对象被创建之后,就被会收集起来,然后可以通过fixture或带有Node.iter_markers的钩子函数访问,可以访问到这个mark对象的属性。

    有 2 个属性:

    • mark.args:这是个元组
    • mark.kwargs:这是个字典

    所以我们可以使用上面的方式来进行传参,比如现在新建一个自定义mark:

    @pytest.mark.timeout(10, "slow", method="thread")
    def test_function():
        ...
    

    这里传参实际上就是

    mark.args == (10, "slow")
    mark.kwargs == {"method": "thread"}
    

    回到最上方的示例代码,在fixture函数中就可以使用data = marker.args[0]来获取到参数42

    如果在测试函数上同时使用了多个自定义mark,那么举例测试函数最近的mark就会被首先迭代。比如:

    @pytest.mark.timeout(10, "slow", method="thread")
    @pytest.mark.slow
    def test_function():
        ...
    

    结果就是先@pytest.mark.slow,然后是@pytest.mark.timeout

    2. 注册自定义的mark

    在运行最上方的示例代码时出现了一个warning,因为我们没有注册自定义的标记导致,现在来进行注册。

    新建pytest.ini配置文件,在里面添加即可:

    [pytest]
    markers =
        fixt_data: pingguo test
        fixt_data2
    

    这里冒号:后面的描述是可选的,比如fixt_data2就是没有添加描述。

    重新执行下最上方的代码:

    platform win32 -- Python 3.9.12, pytest-7.1.3, pluggy-1.0.0
    rootdir: D:\PythonCode\my_python, configfile: pytest.ini
    collected 1 item
    
    usemarks.py .
    
    ============================== 1 passed in 0.00s ==============================
    
    Process finished with exit code 0
    

    注册完成。

    pytest合集见链接

  • 相关阅读:
    Python多线程Thread——生产者消费者模型
    方舟生存进化ARK个人服务器搭建教程保姆级
    【数据结构】线性表之顺序表
    基于transformer的心脑血管心脏病疾病预测
    logback--进阶--02--Logger,Appenders 和 Layouts
    Redis如何实现多可用区?
    前后台同一个端口部署项目
    MAC显示解锁记录(show last times the screen was unlocked in mac os)
    数据库-范式例题
    C语言经典面试题目(十八)
  • 原文地址:https://www.cnblogs.com/pingguo-softwaretesting/p/16644917.html