如何在@ tornado.testing.gen_test中编写要调用的函数?

时间:2014-05-26 15:45:38

标签: python tornado

所以我有一些我想要测试的代码,而且我遇到了@tornado.testing.gen_test预期输入测试基于yield generator的性质的非常可怕的副作用:

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 个答案:

答案 0 :(得分:5)

您应该使用@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

在Python 3.3+中,您可以使用return response代替raise gen.Return(response)。如果您在呼叫站点使用@gen.coroutine,则甚至可以省略yield from