Pytest参数测试用例共享一个类变量

时间:2019-01-24 20:17:48

标签: python pytest

我最近开始使用pytest,并且编写了以下课程。

import pytest
import yaml
import random

testcases = list()
class TestSample(object):
    test_yml_file = "/tmp/test_inputs.yml"

    yamlTestList = list()
    with open(test_yml_file, 'r') as testYamlFile:
        yamlTestList = yaml.load(testYamlFile)

    global testcases
    testcases = []

    for d in yamlTestList['testcases']:
        temp = dict()
        for k,v in d.items():
            temp[k] = v
        testcases.append((temp['testcase'],temp))

    last_value = 2

    @classmethod
    def setup_class(self):
        test_sample = TestSample()

    @pytest.mark.debug
    @pytest.mark.parametrize(('testname', 'testInput'), testcases)
    def test_run(self,testname,testInput):
        if last_value >= 10:
            last_value += random.randint(1,10)

当前问题是- 对于每个参数化测试,last_value始终设置为2。我们如何使用在前一个测试用例中更改为当前测试用例的'last_value'变量的值?

1 个答案:

答案 0 :(得分:0)

答案:

您将需要在外部范围内实例化lastvalue变量,可以从中调用参数化的函数,而不是在测试类本身中。这是因为参数化如何与pytest一起使用。每个带有每个参数集的函数调用都位于一个单独的范围内,因此,在代码中,基本上每次调用该函数之前,都将lastvalue变量重置为2。

解决方案1:

我不建议使用全局变量,但是按照您的示例,这表明了我在说什么。


last_value = 0


class TestSample(object):
    testcases = [("name1", 1), ("name2", 2), ("name3", 3), ("name4", 4)]

    @pytest.mark.parametrize(('testname', 'testInput'), testcases)
    def test_run(self, testname, testInput):
        global last_value
        if last_value >= 10:
            last_value += random.randint(1, 10)
        else:
            last_value += 5

        print(last_value)

还请注意,我在函数中添加了else子句进行测试。即使参数化的工作方式类似于单个类实例中的循环,lastvalue变量也永远不会在示例代码中发生变化,因为if last_value >= 10子句永远不会被满足,因此{ {1}}实际上从未发生过增量。

最佳解决方案:

我建议不要使用具有“类”范围的pytest固定装置,而不要使用全局变量。您可以阅读有关灯具和灯具范围in the pytest docs here.

的信息。
lastvalue

@pytest.fixture(name="sample_manager", scope="class") def sample_manager_fixture(): class SampleManager: def __init__(self): self.last_value = 0 return SampleManager() class TestSample: testcases = [("name1", 1), ("name2", 2), ("name3", 3), ("name4", 4)] def test_order(self, sample_manager): print(sample_manager.last_value) @pytest.mark.parametrize(('testname', 'testInput'), testcases) def test_run(self, testname, testInput, sample_manager): if sample_manager.last_value >= 10: sample_manager.last_value += random.randint(1, 10) else: sample_manager.last_value += 5 print(sample_manager.last_value) 固定装置函数在传递给测试函数时将返回一个sample_manager_fixture()类实例。 Pytest在后台处理所有这些,因此您需要做的就是将灯具名称(在我的情况下明确声明)作为参数。固定装置范围定义了从固定装置返回的每个特定对象实例的“寿命”。因此,将夹具的范围设置为“类”会通知pytest您希望特定类中的所有测试函数共享从夹具返回的对象的相同实例。您可以从所需的固定装置中返回具有任何结构的任何对象,因此它们是管理整个测试数据的强大工具。