是否可以为 class-实例范围创建一个 pytest fixture?

Is it possible to create a pytest fixture for class-instance scope?

假设我有多组参数:

[
  ('a', 'b'),
  ('c', 'd'),
  ('e', 'f')
]

这组参数不是静态的。它是从另一个函数中获取的。

所以在我的例子中,使用这组参数对 class 进行参数化非常方便:

@pytest.mark.parametrize('a, b', [
  ('a', 'b'),
  ('c', 'd'),
  ('e', 'f')
])
class TestClass:
def test_a(self, a, b):
    print(a)
def test_b(self, a, b):
    print(b)

但我也有需要根据这些值 ab 计算第三个值 c 的情况。 值 c 的计算是一项非常耗时的任务,所以我想将它移动到固定装置(类似这样的东西):

@pytest.mark.parametrize('a, b', [
      ('a', 'b'),
      ('c', 'd'),
      ('e', 'f')
])
class TestClass:
    @pytest.fixture
    def calculate_c(a, b):
        return a + b

    def test_a(self, a, b, calculate_c):
        print(a)

    def test_b(self, a, b, calculate_c):
        print(b)    

很明显,函数calculate_c的结果对于每组参数都是不同的。

我知道pytest中有一个scope="class",但是根据我的实验,这不是我需要的

谁能帮我解决这个问题?

谢谢!

这似乎有效。当然,如果 c 的大小很大,而且参数的数量很多,您可能会开始付出显着的内存成本来存储它们。不幸的是,您不能一次只存储一个,因为 pytest 在继续 test_b.

之前对每个参数对运行 test_a

导入 pytest

@pytest.mark.parametrize('a, b', [
      ('a', 'b'),
      ('c', 'd'),
      ('e', 'f')
])
class TestClass:

    @classmethod
    def calculate_c(self, a, b):
        try:
            if self.c_map[(a,b)]:
                print("didn't calculate")
                return self.c_map[(a,b)]
        except AttributeError:
            self.c_map = {}
        except KeyError:
            pass

        self.c_map[(a, b)] = a+b # do whatever expensive computation here                                                                                  
        return self.c_map[(a,b)]


    def test_a(self, a, b):
        c = self.calculate_c(a, b)
        print(a, c)

    def test_b(self, a, b):
        c = self.calculate_c(a, b)
        print(b, c)

产生:

a ab
.c cd
.e ef
.didn't calculate
b ab
.didn't calculate
d cd
.didn't calculate
f ef
.