为不同的测试赋予 Pytest 装置不同的范围

Rub*_*byM 8 fixtures pytest

在我的测试套件中,我有某些数据生成装置,可用于许多参数化测试。其中一些测试希望这些装置在每个会话中仅运行一次,而其他测试则需要它们运行每个功能。例如,我可能有一个类似于以下的装置:

@pytest.fixture
def get_random_person():
    return random.choice(list_of_people)
Run Code Online (Sandbox Code Playgroud)

以及 2 项参数化测试,一项是针对每种测试条件使用同一个人,另一项是每次都需要一个新人。有什么方法可以让这个固定装置为一个测试设置范围=“会话”,为另一个测试设置范围=“功能”吗?

Err*_*rse 7

詹姆斯的回答yield是好的,但如果你从你的固定代码中得到答案,这并没有帮助。这是一个更好的方法:

# Built In
from contextlib import contextmanager

# 3rd Party
import pytest

@pytest.fixture(session='session')
def fixture_session_fruit():
    """Showing how fixtures can still be passed to the different scopes.
    If it is `session` scoped then it can be used by all the different scopes;
    otherwise, it must be the same scope or higher than the one it is used on.
    If this was `module` scoped then this fixture could NOT be used on `fixture_session_scope`.
    """
    return "apple"

@contextmanager
def _context_for_fixture(val_to_yield_after_setup):
    # Rather long and complicated fixture implementation here
    print('SETUP: Running before the test')
    yield val_to_yield_after_setup # Let the test code run
    print('TEARDOWN: Running after the test')

@pytest.fixture(session='function')
def fixture_function_scope(fixture_session_fruit):
    with _context_for_fixture(fixture_session_fruit) as result:
        yield result

@pytest.fixture(scope='class')
def fixture_class_scope(fixture_session_fruit):
    with _context_for_fixture(fixture_session_fruit) as result:
        yield result

@pytest.fixture(scope='module')
def fixture_module_scope(fixture_session_fruit):
    with _context_for_fixture(fixture_session_fruit) as result:
        yield result

@pytest.fixture(scope='session')
def fixture_session_scope(fixture_session_fruit):
    with _context_for_fixture(fixture_session_fruit) as result:
        # NOTE if the `_context_for_fixture` just did `yield` without any value,
        # there should still be a `yield` here to keep the fixture
        # inside the context till it is done. Just remove the ` result` part.
        yield result
Run Code Online (Sandbox Code Playgroud)

这样您仍然可以处理上下文固定装置。

Github问题供参考:https ://github.com/pytest-dev/pytest/issues/3425


小智 4

一种方法是分离出实现,然后让 2 个不同范围的固定装置返回它。所以像这样:

def _random_person():
    return random.choice(list_of_people)

@pytest.fixture(scope='function')
def get_random_person_function_scope():
    return _random_person()

@pytest.fixture(scope='session')
def get_random_person_session_scope():
    return _random_person()
Run Code Online (Sandbox Code Playgroud)