如何在nose测试中调用生成器并让nose处理?
我正在尝试创建一个通用的数据驱动测试处理器,这样我就可以在我的nose测试中调用它。我的测试文件大概是这样的:
import ScenarioHandler
def test_foo():
scenario = ScenarioHandler(__test_foo, [1, 2])
scenario.run()
def __test_foo(var):
assert var % 2 == 0, 'Odd!'
ScenarioHandler可能长这样:
class ScenarioHandler(object):
def __init__(self, test, args):
self.test = test
self.args = args
def run(self):
for arg in self.args:
yield self.test, arg
我遇到的问题是,我不知道怎么把ScenarioHandler.run()
中的生成器传回nose。我试过在test_foo()
中从run()
返回生成器,但这样也不行。这真的有可能吗?
2 个回答
0
你为什么不试试这样的写法:
def test_foo():
for var in [1, 2]:
yield __test_foo, var
另外,可以看看我在这个回答中提到的add_tests(generator)
函数。
0
我不太清楚这个 nose
的东西具体是怎么运作的。
不过你给出的例子是行不通的。
你有一个调用树:
test_foo()
-> run()
。
因为 run()
返回的是一个生成器,而这个生成器在开始迭代之前是不会启动的,所以你需要进行迭代。
你可以这样做:
def test_foo():
scenario = ScenarioHandler(__test_foo, [1, 2])
for f, a in scenario.run():
f(a)
或者更好的是,因为 nose
已经提供了这个功能,可以通过明确测试给定函数的标志来实现,使用 func.func_code.co_flags & CO_GENERATOR != 0
,
def test_foo():
scenario = ScenarioHandler(__test_foo, [1, 2])
for f, a in scenario.run():
yield f, a
这样 nose
就能进行这些调用。
(其实还有一种更简短的方法,就是使用
test_meth = ScenarioHandler(__test_foo, [1, 2]).run
但可惜的是,这种方法不行,因为方法显然没有被正确识别为有效的调用目标。)
不过你可以在你的类里添加一个“测试生成器”。
# as method:
def make_test(self):
def test_generator():
for item in self.run():
yield item
return test_generator
这样你就可以这样做:
test_foo = ScenarioHandler(__test_foo, [1, 2]).make_test()
但可能 nose
提供了更好的方式,通过继承 TestCase
和 TestSuite
来将你的测试封装在类里。