【问题标题】:Give Pytest fixtures different scopes for different tests为不同的测试赋予 Pytest 固定装置不同的范围
【发布时间】:2018-12-12 18:33:38
【问题描述】:

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

@pytest.fixture
def get_random_person():
    return random.choice(list_of_people)

和 2 个参数化测试,一个希望在每个测试条件下使用同一个人,另一个希望每次都使用一个新人。有没有办法让这个夹具有一个测试的 scope="session" 和另一个测试的 scope="function"?

【问题讨论】:

  • 范围在测试执行之前进行评估,之后无法更改。有一个 open issue 提议动态范围(因此您可以将可调用对象作为范围参数传递),但尚未实现。

标签: pytest fixtures


【解决方案1】:

这样做的一种方法是分离出实现,然后让 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()

【讨论】:

    【解决方案2】:

    James' answer 没问题,但如果您从夹具代码中yield 则无济于事。这是一个更好的方法:

    from contextlib import contextmanager
    
    @pytest.fixture(session='session')
    def multiple_usecase_fixture():
        yield "Some string"
    
    @pytest.fixture(session='function')
    def my_fixture_fun(multiple_usecase_fixture):
        with _fixture_impl(multiple_usecase_fixture) as result:
            yield result
    
    @pytest.fixture(scope='module')
    def my_fixture_mod(multiple_usecase_fixture):
        with _fixture_impl(multiple_usecase_fixture) as result:
            yield result
    
    @pytest.fixture(scope='session')
    def my_fixture_ses(multiple_usecase_fixture):
        with _fixture_impl(multiple_usecase_fixture) as result:
            yield result
    
    @contextmanager
    def _fixture_impl(multiple_usecase_fixture):
        # Rather long on complicated fixture implementation here
        print('SETUP: Fixture implmentation')
        yield
        print('TEARDOWN: Fixture implmentation')
    

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

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

    【讨论】:

      【解决方案3】:

      实际上有一个使用请求对象的解决方法。 你可以这样做:

      @pytest.fixture(scope='class')
      def get_random_person(request):
          request.scope = getattr(request.cls, 'scope', request.scope)
          return random.choice(list_of_people)
      

      然后回到测试课:

      @pytest.mark.usefixtures('get_random_person')
      class TestSomething:
          scope = 'function'
      
          def a_random_test():
      
          def another_test():
      

      但是,这仅适用于在“功能”和“类”范围之间进行选择,尤其是当夹具以类范围开始时(然后更改为“功能”或保持原样)。 如果我尝试反过来(从“功能”到“类”)发生有趣的事情,我仍然无法弄清楚为什么。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-06-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多