pytest学习总结3.1 - 固定装置 fixture 深入解读

3.1 固定装置 - fixture

3.1.1 一些内置的固定装置

  • capfd 捕获为文本,输出到文件描述符1和2
  • capfdbinary 捕获为字节符,输出到文件描述符1和2。
  • caplog 控制日志记录和访问日志项。
  • capsys 捕获,作为文本,输出到sys.stdout和sys.stderr
  • capsysbinary 捕获为字节,输出到sys.stdout和sys.stderr。
  • cache 在最测试运行中存储和检索值。
  • doctest_namespace 提供一个注入到文档目录名称空间中的字典。
  • monkeypatch 临时修改类、函数、字典、操作系统、环境和其他对象。
  • pytestconfig 访问配置值、插件管理器和插件钩子
  • record_property 向测试中添加额外的属性。
  • record_testsuite_property 向测试套件中添加额外的属性。
  • recwarn 记录测试功能发出的警告
  • request 提供有关执行测试功能的信息
  • testdir 提供一个临时测试目录,以帮助运行和测试测试插件。
  • tmp_path 提供一个路径。路径对象到一个临时目录,该目录对每个测试函数都是唯一的。
  • tmp_path_factory 创建具有会话作用域的临时目录,并返回路径库。路径对象。
  • tmpdir 为一个临时目录提供一个py.path.local对象,该目录对每个测试函数都是唯一的;被tmp_path取代。
  • tmpdir_factory 创建会话作用域的临时目录并返回py.path.local对象;取代了tmp_path_factory。

3.1.2 固定装置如何使用?

一个夹具也可以请求任何其他夹具,无论它是在哪里定义的,只要请求它们的测试可以看到所有涉及的固定装置。从测试的角度来看,他们可以毫无问题地看到他们所依赖的每个固定装置

import pytest
@pytest.fixture
def order():
    return []
@pytest.fixture
def outer(order, inner):
    order.append("outer")
class TestOne:
    @pytest.fixture
    def inner(self, order):
        order.append("one")
    def test_order(self, order, outer):
        assert order == ["one", "outer"]
class TestTwo:
    @pytest.fixture
    def inner(self, order):
        order.append("two")
    def test_order(self, order, outer):
        assert order == ["two", "outer"]

image.png

1、来自conftest.py的固定装置

  • conftest.py 文件用作为整个目录提供固定装置的一种方式,跨多个文件共享固定装置
  • 在conftest.py 中定义的夹具,可以被该包中的任何测试使用,而无需导入它们(pytest 将自动发现它们),
  • 你可以有多个包含测试的嵌套目录/包,并且每个目录都可以有自己的 conftest.py
  • 这些目录成为它们自己的范围,其中在该目录的 conftest.py 文件中定义的夹具可用于整个范围,允许测试向上搜索(走出圆圈)寻找夹具,但永远不能向下搜索继续他们的搜索。 所以tests/subpackage/test_subpackage.py::test_order 将能够找到在tests/subpackage/test_subpackage.py中定义的最里面的fixture,但是在tests/subpackage/test_subpackage.py中定义的那个tests/test_top.py 将不可用,
tests/
    __init__.py

    conftest.py
        # content of tests/conftest.py
        import pytest
        @pytest.fixture
        def order():
            return []
        @pytest.fixture
        def top(order, innermost):
            order.append("top")
            
    test_top.py
        # content of tests/test_top.py
        import pytest
        @pytest.fixture
        def innermost(order):
            order.append("innermost top")
        def test_order(order, top):
            assert order == ["innermost top", "top"]
            
    subpackage/
        __init__.py

        conftest.py
            # content of tests/subpackage/conftest.py
            import pytest
            @pytest.fixture
            def mid(order):
                order.append("mid subpackage")
        test_subpackage.py
            # content of tests/subpackage/test_subpackage.py
            import pytest
            @pytest.fixture
            def innermost(order, mid):
                order.append("innermost subpackage")
            def test_order(order, top):
                assert order == ["mid subpackage", "innermost subpackage", "top"]

image.png

2、来自第三方插件的固定装置

如果安装了plugin_a并提供了夹具a_fix,并且安装了plugin_b并提供了夹具b_fix,那么这就是测试中搜索夹具的结果:

tests/
    __init__.py

    conftest.py
        # content of tests/conftest.py
        import pytest
        @pytest.fixture
        def order():
            return []

    subpackage/
        __init__.py

        conftest.py
            # content of tests/subpackage/conftest.py
            import pytest
            @pytest.fixture(autouse=True)
            def mid(order, b_fix):
                order.append("mid subpackage")

        test_subpackage.py
            # content of tests/subpackage/test_subpackage.py
            import pytest
            @pytest.fixture
            def inner(order, mid, a_fix):
                order.append("inner subpackage")
            def test_order(order, inner):
                assert order == ["b_fix", "mid subpackage", "a_fix", "inner subpackage˓→"]

image.png

3.1.3 固定装置的调用顺序

当 pytest 想要执行测试时,一旦它知道要执行哪些夹具,它就必须弄清楚它们的执行顺序,它考虑了 3 个因素:

  • scope
  • dependencies
  • autouse

1、首先执行更高范围的固定装置

fixture执行的时候,较高范围(session)的固定装置在较低范围的固定装置之前(class、方法)执行:

import pytest
@pytest.fixture(scope="session")
def order():
    return []

@pytest.fixture
def func(order):
    order.append("function")
@pytest.fixture(scope="class")
def cls(order):
    order.append("class")
@pytest.fixture(scope="module")
def mod(order):
    order.append("module")
@pytest.fixture(scope="package")
def pack(order):
    order.append("package")
@pytest.fixture(scope="session")
def sess(order):
    order.append("session")
class TestClass:
    def test_order(self, func, cls, mod, pack, sess, order):
        assert order == ["session", "package", "module", "class", "function"]

image.png

2、基于依赖关系执行相同顺序的夹具

import pytest
@pytest.fixture
def order():
    return []
@pytest.fixture
def a(order):
    order.append("a")
@pytest.fixture
def b(a, order):
    order.append("b")
@pytest.fixture
def c(a, b, order):
    order.append("c")
@pytest.fixture
def d(c, b, order):
    order.append("d")
@pytest.fixture
def e(d, b, order):
    order.append("e")
@pytest.fixture
def f(e, order):
    order.append("f")
@pytest.fixture
def g(f, c, order):
    order.append("g")

def test_order(g, order):
    assert order == ["a", "b", "c", "d", "e", "f", "g"]

3、固定装置首先在其范围内执行

示例1:

import pytest
@pytest.fixture(scope="class")
def order():
    return []
@pytest.fixture(scope="class", autouse=True)
def c1(order):
    order.append("c1")
@pytest.fixture(scope="class")
def c2(order):
    order.append("c2")
@pytest.fixture(scope="class")
def c3(order, c1):
    order.append("c3")
class TestClassWithC1Request:
    def test_order(self, order, c1, c3):
        assert order == ["c1", "c3"]
class TestClassWithoutC1Request:
    def test_order(self, order, c2):
        assert order == ["c1", "c2"]

image.png
示例2:

import pytest
@pytest.fixture
def order():
    return []
@pytest.fixture
def c1(order):
    order.append("c1")
@pytest.fixture
def c2(order):
    order.append("c2")

class TestClassWithAutouse:
    
    @pytest.fixture(autouse=True)
    def c3(self, order, c2):
        order.append("c3")

    def test_req(self, order, c1):
        assert order == ["c2", "c3", "c1"]
    
    def test_no_req(self, order):
        assert order == ["c2", "c3"]

class TestClassWithoutAutouse:
    
    def test_req(self, order, c1):
        assert order == ["c1"]
    
    def test_no_req(self, order):
        assert order == []

image.png

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阿_焦

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值