问题描述
我一直在使用对我的测试进行参数设置,取得了巨大的成功过去的几个月。现在的问题是我似乎无法注入列表变量作为数据源。这样做似乎会使DDT混淆,导致DDT无法参数化我的测试。我开始创建自己的解决方案,但似乎无法弄清楚最后一部分。
I've been using DDT to parameterize my tests with great success for the past few months. My issue now is that I can't seem to inject a list variable as my data source. Doing so seems to confuse DDT causing it to not parameterize my tests. I started to create my own solution, but I can't seem to figure this last part out.
到目前为止,这是我作为装饰者所拥有的-
Here is what I have thus far as decorators -
def data(*values):
def aaa(func):
def wrapper(self, *args, **kwargs):
pass
# return func(self, *args, **kwargs)
wrapper.func_name = func.__name__ + 't'
wrapper.values = values
return wrapper
return aaa
def c(cls):
for name, method in list(cls.__dict__.items()):
if hasattr(method, 'values'):
for ticket in method.values[0]:
test_name = mk_test_name(method.func_name, ticket)
print(test_name)
setattr(cls, test_name, method(cls, ticket))
return cls
然后我就这样使用它-
@c
class IntegrationTests(APITestCase):
tickets = [1, 2, 3, 4]
@data(tickets)
def tes(self, t):
print(t)
如何使Python测试框架能够识别通过装饰器添加的内容?我知道已经添加了这些方法,因为在PDB中发出 dir
命令会显示它们。这样做的目的是,我将为列表中的每个项目重复装饰的测试。对于那些想知道为什么 wrapper()
没有代码的人,我这样做是因为取消注释该行的return调用会导致我装饰的方法在没有参数的情况下执行,从而导致错误。
How can I make the Python testing framework recognize that I've added via decorator? I know the methods have been added because issuing the dir
command in PDB displays them. The goal for this is that I would duplicate the test(s) I decorate for each item in a list. For those wondering why wrapper()
has no code, I did this because uncommenting the line the return call causes the method I decorate to be executed without parameters, thus causing an error.
在我的示例中,我希望执行4个名称不同的测试。
In my example, I would expect 4 tests with different names to be executed.
推荐答案
最好的解决方案是在python 3.4中使用unittest的子测试功能。在找到的文档,其使用方式如下:
The best solution is to use the sub tests feature of unittest in python 3.4. Documentation found here and used like:
class NumbersTest(unittest.TestCase):
def test_even(self):
"""
Test that numbers between 0 and 5 are all even.
"""
for i in range(0, 6):
with self.subTest(i=i):
self.assertEqual(i % 2, 0)
使用python 3.4,以下是一个穷人的替代品。
For those who cannot use python 3.4, the following is a poor man's replacement.
class sub_test_data(object):
def __init__(self, *test_data):
self.test_data = test_data
def __call__(self, func):
func.sub_test_data = self.test_data
func.has_sub_tests = True
return func
def create_test_driver(func, *args):
def test_driver(self):
try:
func(self, *args)
except AssertionError as e:
e.args += ({"test_args": args},)
raise
return test_driver
def create_sub_tests(cls):
for attr_name, func in list(vars(cls).items()):
if getattr(func, "has_sub_tests", False):
for i, value in enumerate(func.sub_test_data):
test_name = 'test_{}_subtest{}'.format(attr_name, i)
setattr(cls, test_name, create_test_driver(func, value))
return cls
@create_sub_tests
class NumbersTest(unittest.TestCase):
tickets = [0, 1, 2, 3, 4, 5]
@sub_test_data(*tickets)
def even(self, t):
self.assertEqual(t % 2, 0)
这篇关于使用装饰器动态添加测试方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!