【问题标题】:How can I use a parametrized dependent fixture twice in pytest?如何在 pytest 中两次使用参数化的依赖夹具?
【发布时间】:2019-05-31 08:32:21
【问题描述】:

我试图在一次测试中多次使用参数化夹具,目的是获得所有值的笛卡尔积。

https://stackoverflow.com/a/39444098/102441 展示了如何为一个简单的夹具执行此操作:

import pytest

@pytest.fixture(params=[0, 1, 2])
def first(request):
    return request.param

second = first

# runs 3x3 = 9 times
def test_double_fixture(first, second):
    assert False, '{} {}'.format(first, second)

但是,如果参数化来自依赖的夹具,这种方法就会失败:

import pytest

@pytest.fixture(params=[0, 1, 2])
def integer(request):
    return request.param

@pytest.fixture
def squared_integer(integer):
    return integer * integer

@pytest.fixture
def first(squared_integer):
    return squared_integer

second = first

# runs only 3 times
def test_double_fixture(first, second):
    assert False, '{} {}'.format(first, second)

我怎样才能像简单示例那样运行 3x3 测试?

【问题讨论】:

    标签: python pytest fixtures


    【解决方案1】:

    这是 pytest 的正确行为。因为您在其他灯具内部使用integer。要了解会发生什么,请使用 --setup-show 标志检查 pytest。你会看到类似的东西:

            SETUP    F integer[0]
            SETUP    F squared_integer (fixtures used: integer)
            SETUP    F first (fixtures used: squared_integer)
            SETUP    F second (fixtures used: squared_integer)
            Test/test_54044536_3.py::test_double_fixture[0] (fixtures used: first, integer, second, squared_integer)F
            TEARDOWN F second
            TEARDOWN F first
            TEARDOWN F squared_integer
            TEARDOWN F integer[0]
    

    因此整数值仅适用于 squared_integer 函数。

    为了回答您的问题,我们可以将您的代码重构为固定装置和一个函数。这看起来像:

    import pytest
    
    def squared_integer(integer):
        return integer * integer
    
    
    @pytest.fixture(params=[0, 1, 2])
    def first(request):
        return squared_integer(request.param)
    
    second = first
    
    # runs only 3 times
    def test_double_fixture(first, second):
        assert False, '{} {}'.format(first, second)
    

    您将有 9 个具有这样顺序的测试:

            SETUP    F first[0]
            SETUP    F second[0]
            Test/test_54044536_2.py::test_double_fixture[0-0] (fixtures used: first, second)F
            TEARDOWN F second[0]
            TEARDOWN F first[0]
            SETUP    F first[0]
            SETUP    F second[1]
            Test/test_54044536_2.py::test_double_fixture[0-1] (fixtures used: first, second)F
            TEARDOWN F second[1]
            TEARDOWN F first[0]
            SETUP    F first[0]
            SETUP    F second[2]
            Test/test_54044536_2.py::test_double_fixture[0-2] (fixtures used: first, second)F
            TEARDOWN F second[2]
            TEARDOWN F first[0]
            SETUP    F first[1]
            SETUP    F second[0]
            Test/test_54044536_2.py::test_double_fixture[1-0] (fixtures used: first, second)F
            TEARDOWN F second[0]
            TEARDOWN F first[1]
            SETUP    F first[1]
            SETUP    F second[1]
            Test/test_54044536_2.py::test_double_fixture[1-1] (fixtures used: first, second)F
            TEARDOWN F second[1]
            TEARDOWN F first[1]
            SETUP    F first[1]
            SETUP    F second[2]
            Test/test_54044536_2.py::test_double_fixture[1-2] (fixtures used: first, second)F
            TEARDOWN F second[2]
            TEARDOWN F first[1]
            SETUP    F first[2]
            SETUP    F second[0]
            Test/test_54044536_2.py::test_double_fixture[2-0] (fixtures used: first, second)F
            TEARDOWN F second[0]
            TEARDOWN F first[2]
            SETUP    F first[2]
            SETUP    F second[1]
            Test/test_54044536_2.py::test_double_fixture[2-1] (fixtures used: first, second)F
            TEARDOWN F second[1]
            TEARDOWN F first[2]
            SETUP    F first[2]
            SETUP    F second[2]
            Test/test_54044536_2.py::test_double_fixture[2-2] (fixtures used: first, second)F
            TEARDOWN F second[2]
            TEARDOWN F first[2]
    
    

    【讨论】:

      【解决方案2】:

      如果您对顶层夹具的副本没有问题(在这种情况下 squared_integer 的化身为 first 和 second),您也可以复制低层夹具并将其用作另一个输入一级:

      import pytest
      
      @pytest.fixture(params=[0, 1, 2])
      def integer(request):
          return request.param
      integer2 = integer
      
      @pytest.fixture
      def squared_integer(integer, integer2):
          return integer * integer2
      second = first = squared_integer
      
      # runs 9 times
      def test_double_fixture_lowlevel(integer, integer2):
          assert False, '{} {}'.format(integer, integer2)
      
      # also runs 9 times
      def test_double_fixture_toplevel(first, second):
          assert False, '{} {}'.format(first, second)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-12-25
        • 2023-03-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-11-23
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多