Django单元测试:self属性修改在测试间持久化问题求助
字典修改在Django测试中跨用例残留的问题
从test_helpers文件导入包含默认数据的字典FORM_DATA,初始值为FORM_DATA['value_A'] = 0、FORM_DATA['value_B'] = 1000000。
无论将FORM_DATA赋值给self.form_data,还是在每个测试方法中赋值给变量,第二个测试都会保留第一个测试对字典的修改,不符合测试预期。添加打印语句调试后发现,即使在第二个测试的setUp()方法中,也显示着上一个测试修改后的值,每次新测试时self.form_data无法恢复为导入的默认数据。
测试代码
from test_helpers import FORM_DATA class TestBaselineScenarios(TestCase): @classmethod def setUpClass(cls): super(TestBaselineScenarios, cls).setUpClass() long_running_data_setup() def setUp(self): self.form_data = FORM_DATA print("setUp", self.form_data['value_A'], self.form_data['value_B']) def test_one(self): print("1") print(self.form_data['value_A'], self.form_data['value_B']) self.form_data['value_A'] = 25000 self.form_data['value_B'] = 700000 print("2") print(self.form_data['value_A'], self.form_data['value_B']) simulation = test_helpers.create_simulation(form_data=self.form_data) simulation.run() self.assertEqual(0.8416667, round(simulation.success_rate(), 7)) def test_two(self): print("3") print(self.form_data['value_A'], self.form_data['value_B']) self.form_data['value_A'] = 10000 print("4") print(self.form_data['value_A'], self.form_data['value_B']) simulation = test_helpers.create_simulation(form_data=self.form_data) simulation.run() self.assertEqual(0.9916667, round(simulation.success_rate(), 7))
打印输出
setUp 0 1000000 1 0 1000000 2 25000 700000 setUp 25000 700000 3 25000 700000 4 10000 700000
问题原因
Python中字典是可变对象,导入的FORM_DATA是一个全局内存引用。当你执行self.form_data = FORM_DATA时,只是把这个全局引用赋值给了实例变量,并没有创建新的字典对象。测试方法中修改self.form_data的键值,实际上是直接修改了全局的FORM_DATA字典本身,所有测试用例共享同一个字典实例,因此修改会在测试间残留。
解决方法
1. 创建字典浅拷贝
在setUp中为self.form_data赋值字典的副本,避免直接操作全局对象:
def setUp(self): self.form_data = FORM_DATA.copy() # 浅拷贝 print("setUp", self.form_data['value_A'], self.form_data['value_B'])
如果FORM_DATA是嵌套字典(包含其他可变对象),需要使用深拷贝:
import copy def setUp(self): self.form_data = copy.deepcopy(FORM_DATA) # 深拷贝
2. 用函数返回新字典
修改test_helpers文件,定义一个返回新字典的函数,每次调用都会生成独立的字典实例:
# test_helpers.py def get_form_data(): return {'value_A': 0, 'value_B': 1000000}
在测试类中调用该函数获取初始数据:
from test_helpers import get_form_data def setUp(self): self.form_data = get_form_data()
3. 在setUp中重新初始化
直接在setUp里手动初始化字典,完全脱离全局引用:
def setUp(self): self.form_data = {'value_A': 0, 'value_B': 1000000}
内容的提问来源于stack exchange,提问作者Lauren Boland
相关产品推荐
相关产品推荐

