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"的值用于当前测试用例?

答案:

您需要在外部作用域中实例化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子句从未得到满足,因此lastvalue增量从未实际发生。

最佳解决方案:

我建议使用具有"类"作用域的pytest fixture,而不是使用全局。您可以在这里的pytest文档中阅读关于fixture和fixture作用域的信息。

@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()fixture函数在传递给测试函数时返回一个SampleManager类实例。Pytest在幕后处理所有这些,所以您所需要做的就是将fixture名称(在本例中明确声明)作为参数。fixture范围定义了从fixture返回的每个特定对象实例的"寿命"。因此,将fixture的作用域设置为"class"会通知pytest,您希望特定类中的所有测试函数共享从fixture返回的对象的同一实例。您可以从所需的fixture返回任何具有任何结构的对象,因此它们是管理测试中数据的非常强大的工具。

最新更新