如何在单个 python 脚本中设置测试数据和测试用例
How do I set up the test data and the test cases in a single python script
我正在编写单元测试并尝试设置测试数据以用于同一 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
此时我几乎迷路了......
有人对此有线索吗?
所有Python代码都是可执行的。当加载 class 主体时,将执行其中的语句。装饰函数在 def
中创建带有咖啡的函数,将其分配给临时 class 命名空间中的名称(例如 test_whatever_possible
),然后将其替换为调用装饰器。
这很重要的原因是装饰器是在 class 加载时调用的,而不是在测试 运行 时调用的。装饰器 file_data
检查文件是否存在(间接),因为它必须用文件中的值调用测试的函数替换测试函数。
您的第二个 运行 通过了,因为第一个 运行 已经创建了测试文件。我建议在 GitHub 上填写一个问题。 file_data
需要延迟打开文件,或者需要在某处清楚地记录意外行为。
您可以在 source code.file_data
merely flags your test function for further processing. process_file_data
中确切地看到这种魔法发生的位置,然后检查该文件是否可用于扩展实际测试,或者创建一个只会引发您看到的错误的替换文件。
作为解决方法,您可以编写自己的装饰器来创建数据文件,例如
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")
更新:1 月 31 日
以下示例保留了将参数值传递给测试函数的 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
使用上面的两个示例,您应该能够得出适合您的问题的解决方案。
我正在编写单元测试并尝试设置测试数据以用于同一 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
此时我几乎迷路了...... 有人对此有线索吗?
所有Python代码都是可执行的。当加载 class 主体时,将执行其中的语句。装饰函数在 def
中创建带有咖啡的函数,将其分配给临时 class 命名空间中的名称(例如 test_whatever_possible
),然后将其替换为调用装饰器。
这很重要的原因是装饰器是在 class 加载时调用的,而不是在测试 运行 时调用的。装饰器 file_data
检查文件是否存在(间接),因为它必须用文件中的值调用测试的函数替换测试函数。
您的第二个 运行 通过了,因为第一个 运行 已经创建了测试文件。我建议在 GitHub 上填写一个问题。 file_data
需要延迟打开文件,或者需要在某处清楚地记录意外行为。
您可以在 source code.file_data
merely flags your test function for further processing. process_file_data
中确切地看到这种魔法发生的位置,然后检查该文件是否可用于扩展实际测试,或者创建一个只会引发您看到的错误的替换文件。
作为解决方法,您可以编写自己的装饰器来创建数据文件,例如
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")
更新:1 月 31 日
以下示例保留了将参数值传递给测试函数的 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
使用上面的两个示例,您应该能够得出适合您的问题的解决方案。