AssertionError“assert not”IOLoop.initialized()“关于使用AsyncIOMainLoop测试Tornado应用程序

2024-05-06 10:57:44 发布

您现在位置:Python中文网/ 问答频道 /正文

我在用AsyncHTTPTestCase为使用asyncio事件循环的现有Tornado应用程序编写测试时遇到一些问题。 在这里,我准备了一个简短的模型,在这里我可以重现问题:

应用程序副本

from tornado.platform.asyncio import AsyncIOMainLoop
import asyncio
import tornado.web


class MainHandler(tornado.web.RequestHandler):
    async def get(self, *args, **kwargs):
        self.write("200 OK")

    async def post(self, *args, **kwargs):
        self.write("201 OK")

def make_app():
    AsyncIOMainLoop().install()  # here is how to asyncio loop installed in app I already have
    return tornado.web.Application([
        (r"/", MainHandler),
    ], debug=True)

def start_app():
    app = make_app()
    app.listen(8888)
    loop = asyncio.get_event_loop()
    loop.set_debug(True)
    loop.run_forever()

开始.py

^{pr2}$

测试_应用程序副本

import json
from tornado.testing import AsyncHTTPTestCase

import app

class TestHelloApp(AsyncHTTPTestCase):
    def get_app(self):
        return app.make_app()

    def test_get(self):
        response = self.fetch('/')
        self.assertEqual(response.code, 200)
        self.assertEqual(response.body.decode(), '200 OK')

    def test_post(self):
        response = self.fetch('/', method="POST",
                              body=json.dumps({"key": "value"}))
        self.assertEqual(response.code, 200)
        self.assertEqual(response.body.decode(), '201 OK')

使用这种安装方法,asyncio loop应用程序可以正常工作(我的意思是我可以执行请求并获得响应),但是这样的测试失败了,错误如下:

======================================================================
FAIL: test_post (test_app.TestHelloApp)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/biceps/work/torn/.venv/lib/python3.6/site-packages/tornado/testing.py", line 380, in setUp
    self._app = self.get_app()
  File "/home/biceps/work/torn/test_app.py", line 8, in get_app
    return app.make_app()
  File "/home/biceps/work/torn/app.py", line 14, in make_app
    tornado.platform.asyncio.AsyncIOMainLoop().install()
  File "/home/biceps/work/torn/.venv/lib/python3.6/site-packages/tornado/ioloop.py", line 181, in install
    assert not IOLoop.initialized()
AssertionError

----------------------------------------------------------------------
Ran 2 tests in 0.006s

FAILED (failures=1)

似乎是由AsyncIOMainLoop()安装的循环。install()命令在测试之间并没有停止,第一个测试通过正常,但第二个测试总是失败。在

当我将AsyncIOMainLoop().install()移到start_app()方法时-测试通过得很好,但我担心在测试期间我使用一个事件循环,但在实际运行的应用程序中我使用asyncio循环。在

因此,针对这些代码测试是通过的:

from tornado.platform.asyncio import AsyncIOMainLoop
import asyncio
import tornado.web


class MainHandler(tornado.web.RequestHandler):
    async def get(self, *args, **kwargs):
        self.write("200 OK")

    async def post(self, *args, **kwargs):
        self.write("201 OK")

def make_app():
    return tornado.web.Application([
        (r"/", MainHandler),
    ], debug=True)

def start_app():
    AsyncIOMainLoop().install()
    app = make_app()
    app.listen(8888)
    loop = asyncio.get_event_loop()
    loop.set_debug(True)
    loop.run_forever()

Q:我的问题是-如何在该用例中正确地编写测试?当Tornado应用程序使用AsyncIOMainLoop时,如何使用AsyncHTTPTestCase编写测试? 我决定将AsyncIOMainLoop().install()设置为start_app(),而不是make\u app()函数,对吗?在

另外,我已经补充了self.io_循环.clear_instance()到tearDown()-它看起来可能很脏,但在从make\u app()代码调用AsyncIOMainLoop().install()的情况下,它看起来可能很脏。在

    def tearDown(self):
    self.io_loop.clear_instance()
    super().tearDown()

Tags: installinimportselfloopwebasyncioapp
1条回答
网友
1楼 · 发布于 2024-05-06 10:57:44

根据文档,我需要在启动应用程序之前安装AsyncIOMainLoop,而不是在制作应用程序时。 documentation

from tornado.platform.asyncio import AsyncIOMainLoop
import asyncio
AsyncIOMainLoop().install()
asyncio.get_event_loop().run_forever()

所以现在我确定正确的方法是使用AsyncIOMainLoop安装到start\u app()代码中。在

现在我的模式代码如下:

web1.py

^{pr2}$

测试_应用程序副本

from tornado.testing import AsyncHTTPTestCase

import web1

class TestTornadoAppBase(AsyncHTTPTestCase):
    def get_app(self):
        return web1.make_app()

    def get_new_ioloop(self):
        """
        Needed to make sure that I can also run asyncio based callbacks in my tests
        """
        io_loop = tornado.platform.asyncio.AsyncIOLoop()
        asyncio.set_event_loop(io_loop.asyncio_loop)
        return io_loop

class TestGET(TestTornadoAppBase):
    def test_root_get_method(self):
        response = self.fetch("/")
        self.assertEqual(response.code, 200)
        self.assertEqual(response.body.decode(), 'OK')

    def test_root_post_method(self):
        response = self.fetch("/", method="POST", body="{}")
        self.assertEqual(response.code, 200)
        self.assertEqual(response.body.decode(), 'OK')

此模式也可以工作,在测试期间使用AsyncIOMainLoop。所以我可以使用使用异步循环的库。在我的例子中异步睡眠()例如。在

相关问题 更多 >