Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/281.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 断言者;断言不是IOLoop.initialized();使用AsyncIOMainLoop测试Tornado应用程序_Python_Unit Testing_Tornado_Python Asyncio - Fatal编程技术网

Python 断言者;断言不是IOLoop.initialized();使用AsyncIOMainLoop测试Tornado应用程序

Python 断言者;断言不是IOLoop.initialized();使用AsyncIOMainLoop测试Tornado应用程序,python,unit-testing,tornado,python-asyncio,Python,Unit Testing,Tornado,Python Asyncio,我在为使用asyncio事件循环的现有Tornado应用程序编写AsyncHTTPTestCase测试时遇到一些问题。 在这里,我准备了一个简短的模型,在这里我可以复制问题: app.py from tornado.platform.asyncio import AsyncIOMainLoop import asyncio import tornado.web class MainHandler(tornado.web.RequestHandler): async def get(s

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

app.py

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()
#!/usr/bin/env python3
import app

if __name__ == "__main__":
    app.start_app()
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')
class MainHandler(tornado.web.RequestHandler):
    async def get(self, *args, **kwargs):
        await asyncio.sleep(1)
        return self.write("OK")

    async def post(self, *args, **kwargs):
        await asyncio.sleep(1)
        return self.write("OK")

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

def start_app():
    from tornado.platform.asyncio import AsyncIOMainLoop
    import asyncio
    AsyncIOMainLoop().install()
    app = make_app()
    app.listen(8888)
    asyncio.get_event_loop().run_forever()


if __name__ == "__main__":
    start_app()
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')
start.py

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()
#!/usr/bin/env python3
import app

if __name__ == "__main__":
    app.start_app()
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')
class MainHandler(tornado.web.RequestHandler):
    async def get(self, *args, **kwargs):
        await asyncio.sleep(1)
        return self.write("OK")

    async def post(self, *args, **kwargs):
        await asyncio.sleep(1)
        return self.write("OK")

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

def start_app():
    from tornado.platform.asyncio import AsyncIOMainLoop
    import asyncio
    AsyncIOMainLoop().install()
    app = make_app()
    app.listen(8888)
    asyncio.get_event_loop().run_forever()


if __name__ == "__main__":
    start_app()
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')
测试应用程序py

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()
#!/usr/bin/env python3
import app

if __name__ == "__main__":
    app.start_app()
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')
class MainHandler(tornado.web.RequestHandler):
    async def get(self, *args, **kwargs):
        await asyncio.sleep(1)
        return self.write("OK")

    async def post(self, *args, **kwargs):
        await asyncio.sleep(1)
        return self.write("OK")

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

def start_app():
    from tornado.platform.asyncio import AsyncIOMainLoop
    import asyncio
    AsyncIOMainLoop().install()
    app = make_app()
    app.listen(8888)
    asyncio.get_event_loop().run_forever()


if __name__ == "__main__":
    start_app()
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')
使用这种安装方法,asyncio循环应用程序运行良好(我的意思是我可以执行请求并得到响应),但这样的测试失败,出现错误:

======================================================================
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()命令在测试之间不会停止,第一个测试通过了OK,但第二个测试始终失败

当我将AsyncIOMainLoop().install()移动到启动_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_app()函数的决定正确吗

另外,我已经将self.io\u loop.clear\u instance()添加到了tearDown()-它看起来可能很脏,但这适用于从make\u app()代码调用AsyncIOMainLoop().install()的情况


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

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

现在,我的模式代码如下所示:

web1.py

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()
#!/usr/bin/env python3
import app

if __name__ == "__main__":
    app.start_app()
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')
class MainHandler(tornado.web.RequestHandler):
    async def get(self, *args, **kwargs):
        await asyncio.sleep(1)
        return self.write("OK")

    async def post(self, *args, **kwargs):
        await asyncio.sleep(1)
        return self.write("OK")

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

def start_app():
    from tornado.platform.asyncio import AsyncIOMainLoop
    import asyncio
    AsyncIOMainLoop().install()
    app = make_app()
    app.listen(8888)
    asyncio.get_event_loop().run_forever()


if __name__ == "__main__":
    start_app()
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')
测试应用程序py

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()
#!/usr/bin/env python3
import app

if __name__ == "__main__":
    app.start_app()
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')
class MainHandler(tornado.web.RequestHandler):
    async def get(self, *args, **kwargs):
        await asyncio.sleep(1)
        return self.write("OK")

    async def post(self, *args, **kwargs):
        await asyncio.sleep(1)
        return self.write("OK")

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

def start_app():
    from tornado.platform.asyncio import AsyncIOMainLoop
    import asyncio
    AsyncIOMainLoop().install()
    app = make_app()
    app.listen(8888)
    asyncio.get_event_loop().run_forever()


if __name__ == "__main__":
    start_app()
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。所以我可以使用那些使用异步IO循环的库。在我的示例中有asyncio.sleep()。

假设
AsyncHTTPTestCase
UnitTest.TestCase
的子类,在
TestHelloApp
中,将
get\u app
重命名为
setUp
setUpClass
,因此它将在测试类启动时运行。@Gang谢谢,但get\u app()是从setUp()调用的方法也一样。问题是IOloop在测试运行之间并没有停止(正如我所了解的,我需要一种方法来停止和关闭测试之间的循环)。您还可以使用
IOloop.configure('tornado.platform.asyncio.asynciioloop')
(启动时一次;您可以在导入时执行),而不是在所有测试中重写
get\u new\u IOloop
。在Tornado 5.0中,异步IO循环在可用时默认使用,因此您无需执行任何操作。