如何编写可在 @tornado.testing.gen_test 中调用的函数?
我有一些代码想要测试,但遇到了一些麻烦,这个麻烦跟使用@tornado.testing.gen_test
这个测试工具有关,它需要用到一种叫生成器的东西:
class GameTest(tornado.testing.AsyncHTTPTestCase):
def new_game(self):
ws = yield websocket_connect('address')
ws.write_message('new_game')
response = yield ws.read_message()
# I want to say:
# return response
@tornado.testing.gen_test
def test_new_game(self):
response = self.new_game()
# do some testing
问题是,我不能从生成器中返回一个值,所以我本能的想法是错的。此外,我不能这样做:
class GameTest(tornado.testing.AsyncHTTPTestCase):
def new_game(self):
ws = yield websocket_connect('address')
ws.write_message('new_game')
response = yield ws.read_message()
yield response, True
@tornado.testing.gen_test
def test_new_game(self):
for i in self.new_game():
if isinstance(i, tuple):
response, success = i
break
# do some testing
因为这样我会遇到错误:
AttributeError: 'NoneType' object has no attribute 'write_message'
显然,我可以把整个测试生成的代码放在测试里面,但这样做真的很麻烦,维护起来也很困难等等。难道这个测试模式真的让事情变得这么复杂吗?
1 个回答
5
在异步函数中,你应该使用 @gen.coroutine
,这样这些函数才能被 @gen_test
方法调用,就像在普通代码中一样。@gen_test
是一个适配器,它让你可以在同步的单元测试界面中使用异步代码。
@gen.coroutine
def new_game(self):
ws = yield websocket_connect('address')
ws.write_message('new_game')
response = yield ws.read_message()
raise gen.Return(response)
@tornado.testing.gen_test
def test_new_game(self):
response = yield self.new_game()
# do some testing
在 Python 3.3 及以上版本中,你可以用 return response
来代替 raise gen.Return(response)
。如果你在调用的地方使用 yield from
,甚至可以省略 @gen.coroutine
。