我正在编写一个单元测试,并试图在同一python脚本中设置用于测试用例的测试数据。
但是,当我运行脚本时,它会创建测试数据,但是会打印一条错误消息,指出该数据不存在,从而导致测试失败。只有当我再次运行脚本时,测试才能成功。
下面是我编写的简化脚本,用于了解发生了什么情况。
import unittest
from ddt import ddt, file_data
import pandas
@ddt
class TestWhatever(unittest.TestCase):
@classmethod
def setUpClass(cls):
cls.setup_test_data()
print("setUpClass is running")
@classmethod
def tearDownClass(cls):
print("tearDownClass is running")
@classmethod
def setup_test_data(cls):
data = pandas.DataFrame({'msg':["testing"]})
data = data.transpose()
with open("practice_test.json", "w") as file:
file.write(data.to_json())
print("setup_test_data is running")
@file_data("practice_test.json")
def test_whatever_possible(self, msg):
print("test_whatever_possible is running :", msg)
self.assertEqual('q', 'q')
def test_whatever_impossible(self):
print("test_whatever_impossible is running")
self.assertEqual('n', 'n')
当我运行上面的脚本时,它会打印:
setup_test_data is running
setUpClass is running
test_whatever_impossible is running
.EtearDownClass is running
======================================================================
ERROR: test_whatever_possible_00001_error (main.TestWhatever)
Error!
----------------------------------------------------------------------
Traceback (most recent call last):
File "C:\ddt.py", line 145, in wrapper
return func(self, *args, **kwargs)
File "C:\ddt.py", line 187, in func
raise ValueError(message % file_attr)
ValueError: practice_test.json does not exist
----------------------------------------------------------------------
Ran 2 tests in 0.006s
FAILED (errors=1)
然后在第二次运行:
setup_test_data is running
setUpClass is running
test_whatever_impossible is running
.test_whatever_possible is running : testing
.tearDownClass is running
----------------------------------------------------------------------
Ran 2 tests in 0.005s
OK
我现在很迷路了... 有人对此有任何线索吗?
答案 0 :(得分:0)
所有Python代码都是可执行的。加载类主体时,将执行其中的语句。装饰函数使用def
中的咖啡创建函数,将其分配给临时类名称空间中的名称(例如test_whatever_possible
),然后将其替换为调用装饰器的结果。>
之所以如此重要,是因为在加载类时(而不是在运行测试时)会调用装饰器。装饰器file_data
检查文件是否正确存在,然后(在那里)间接存在,因为它必须用用文件中的值调用测试的函数替换您的测试函数。
您的第二次运行已通过,因为第一次运行已创建测试文件。我建议在GitHub上填写问题。 file_data
需要延迟打开文件,或者意外行为需要明确记录在某个地方。
您可以在source code中确切地看到此魔术发生的位置。file_data
仅标记您的测试函数以进行进一步处理。 process_file_data
然后检查文件是否可用于扩展实际测试,或创建一个替换文件,仅引起您看到的错误。
答案 1 :(得分:0)
作为解决方法,您可以编写自己的装饰器来创建数据文件,例如
def create_data(name):
def decorator(fn):
def decorated(*args, **kwargs):
data = pandas.DataFrame({"msg": ["testing"]})
data = data.transpose()
with open(name, "w") as file:
file.write(data.to_json())
res = fn(*args, **kwargs)
os.unlink(name)
return res
return decorated
return decorator
,然后将其堆叠以进行测试(并删除setup_test_data
步骤):
@ddt
class TestWhatever(unittest.TestCase):
@classmethod
def setUpClass(cls):
print("setUpClass is running")
@classmethod
def tearDownClass(cls):
print("tearDownClass is running")
@create_data("practice_test.json")
@file_data("practice_test.json")
def test_whatever_possible(self):
print("test_whatever_possible is running :")
self.assertEqual("q", "q")
以下示例保留了将参数值传递到测试函数的ddt行为:
import json
import unittest
from ddt import ddt, FILE_ATTR
def create_file_data(value, data):
def wrapper(func):
with open(value, "w") as file:
file.write(json.dumps(data))
# this is what the file_data decorator does
setattr(func, FILE_ATTR, value)
return func
return wrapper
@ddt
class TestWhatever(unittest.TestCase):
@create_file_data("practice_test.json", {"msg": ["testing"]})
def test_file_data(self, msg):
print("test_file_data msg:", msg)
unittest.main()
运行此命令后,输出为:
test_file_data msg: ['testing']
.
----------------------------------------------------------------------
Ran 1 test in 0.001s
使用上面的两个示例,您应该能够为您的问题找到合适的解决方案。