所以我有一些我想要测试的代码,而且我遇到了基于yield generator @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
Run Code Online (Sandbox Code Playgroud)
问题是我无法从生成器返回值,所以我的本能是错误的.此外,我不能这样做:
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
Run Code Online (Sandbox Code Playgroud)
因为那时我遇到了错误:
AttributeError: 'NoneType' object has no attribute 'write_message'
Run Code Online (Sandbox Code Playgroud)
显然,我可以在测试中包含整个测试生成代码,但这非常难看,难以维护等等.这种测试模式是否真的使间接如此困难?
您应该使用@gen.coroutine
异步函数来调用@gen_test
方法,就像在非测试代码中一样. @gen_test
是顶级测试函数的适配器,可以在同步unittest接口中使用异步代码.
@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
Run Code Online (Sandbox Code Playgroud)
在Python 3.3+中,您可以使用return response
而不是raise gen.Return(response)
.@gen.coroutine
如果您yield from
在呼叫站点使用,甚至可以省略.