在py.test中,将灯具标记为灯具有什么意义?

ima*_*hat 3 python pytest

import pytest

@pytest.fixture()
def my_fixture():
    data = {'x': 1, 'y': 2, 'z': 3}
    return data

def test_my_fixture(my_fixture):
    assert my_fixture['x'] == 1
Run Code Online (Sandbox Code Playgroud)

标记my_fixture为pytest有fixture什么好处?看起来该灯具的好处与my_fixture只是一个常规功能(移除装饰器)相同。

我仅在这里看到了好处,my_fixture只需将其作为参数提供给test_my_fixture

@pytest.fixture()
def my_fixture():
    print "\nI'm the fixture"

def test_my_fixture(my_fixture):
    print "I'm the test"
Run Code Online (Sandbox Code Playgroud)

这应该打印:

I'm the fixture
I'm the test
Run Code Online (Sandbox Code Playgroud)

Ser*_*yev 7

如果您未声明my_fixture为灯具,则测试将无法将其用作灯具:

import pytest

def my_fixture():
    data = {'x': 1, 'y': 2, 'z': 3}
    return data

def test_my_fixture(my_fixture):
    assert my_fixture['x'] == 1
Run Code Online (Sandbox Code Playgroud)

该脚本导致错误:

  def test_my_fixture(my_fixture):
E       fixture 'my_fixture' not found
>       available fixtures: cache, capfd, capsys, doctest_namespace, monkeypatch, pytestconfig, record_xml_property, recwarn, tmpdir, tmpdir_factory
>       use 'pytest --fixtures [testpath]' for help on them.
Run Code Online (Sandbox Code Playgroud)

固定装置的目的是在测试前准备一些东西。并在以后杀死它。并且不要成为测试的一部分(例如,记录,报告,异常处理方式等)。这是一个先决条件,它是由其他事物创建的,并且仅用于测试。

如果仅将其声明为函数,然后将其用作函数,则它是函数,而不是夹具。它的失败成为测试的失败,而不是常规框架的运行。

考虑以下示例:

import pytest

@pytest.fixture()
def my_fixture():
    data = {'x': 1, 'y': 2, 'z': 3}
    print('prepare')
    yield data
    print('destroy')

def test_my_fixture(my_fixture):
    print('test it')
    assert my_fixture['x'] == 1
Run Code Online (Sandbox Code Playgroud)

同样在此示例中,尝试取消注释上升线,并观察差异。这将是错误与失败。对于以后如何解释和处理测试结果(例如,由开发人员,QA工程师或分析测试结果的人员),这至关重要。

import pytest

@pytest.fixture()
def my_fixture():
    print('prepare')
    # raise Exception('Oops')
    yield None
    print('destroy')

def test_my_fixture(my_fixture):
    # raise Exception('Booms!')
    print('test it')
Run Code Online (Sandbox Code Playgroud)

在灯具中:

======================================= test session starts ========================================
collected 1 item                                                                                    

t.py E

============================================== ERRORS ==============================================
________________________________ ERROR at setup of test_my_fixture _________________________________

    @pytest.fixture()
    def my_fixture():
        data = {'x': 1, 'y': 2, 'z': 3}
        print('prepare')
>       raise Exception('Oops')
E       Exception: Oops

t.py:7: Exception
===================================== 1 error in 0.03 seconds ======================================
Run Code Online (Sandbox Code Playgroud)

在测试或测试中调用的任何函数中:

======================================= test session starts ========================================
collected 1 item                                                                                    

t.py F

============================================= FAILURES =============================================
_________________________________________ test_my_fixture __________________________________________

my_fixture = {'x': 1, 'y': 2, 'z': 3}

    def test_my_fixture(my_fixture):
>       raise Exception('Booms!')
E       Exception: Booms!

t.py:12: Exception
===================================== 1 failed in 0.03 seconds =====================================
Run Code Online (Sandbox Code Playgroud)

另请注意,这些夹具具有范围:会话,模块,功能。在一个简短的示例中很难证明,但是在那种情况下,对于该范围内的多次测试,夹具只能准备一次(通常只有一次)并销毁。这对于重量级固定装置(例如数据库预填充)很重要。这样的装置通常位于conftest.py目录结构的伪插件中(注意:至少这不是设计要导入的常规模块)。