{"id":7623,"library":"pytest-tornasync","title":"pytest-tornasync","description":"pytest-tornasync is a simple pytest plugin that provides helpful fixtures for testing Tornado (version 5.0 or newer) applications. It simplifies testing native Python 3.5+ coroutines by eliminating the need for decorators like `@pytest.mark.gen_test`. The current version is 0.6.0.post2, with the last release in July 2019, indicating a stalled release cadence and an 'at risk' maintenance status, although the plugin remains functional for its intended purpose.","status":"maintenance","version":"0.6.0.post2","language":"en","source_language":"en","source_url":"https://github.com/eukaryote/pytest-tornasync","tags":["pytest","tornado","async","testing","plugin","fixtures"],"install":[{"cmd":"pip install pytest-tornasync","lang":"bash","label":"Install stable version"}],"dependencies":[{"reason":"Core testing framework, required for the plugin to function.","package":"pytest","optional":false},{"reason":"Asynchronous web framework being tested; version 5.0 or newer is required.","package":"tornado","optional":false}],"imports":[{"note":"pytest-tornasync itself provides fixtures that are automatically discovered by pytest; direct imports from pytest_tornasync are not typically needed for tests.","symbol":"pytest.fixture","correct":"import pytest"},{"note":"Used in the required 'app' fixture to define the Tornado application under test.","symbol":"tornado.web.Application","correct":"import tornado.web"}],"quickstart":{"code":"import pytest\nimport tornado.web\nfrom tornado.testing import AsyncHTTPTestCase\n\n# Define your Tornado application\nclass MainHandler(tornado.web.RequestHandler):\n    async def get(self):\n        self.write(\"Hello, world\")\n\ndef make_app():\n    return tornado.web.Application([\n        (r\"/\", MainHandler),\n    ])\n\n# Define the 'app' fixture for pytest-tornasync\n@pytest.fixture\ndef app():\n    return make_app()\n\n# Write an async test using the http_server_client fixture\nasync def test_main_handler(http_server_client):\n    response = await http_server_client.fetch('/')\n    assert response.code == 200\n    assert response.body == b\"Hello, world\"\n","lang":"python","description":"This quickstart demonstrates how to set up a basic Tornado application and test it using `pytest-tornasync`. The `app` fixture provides the `tornado.web.Application` instance, and the `http_server_client` fixture (provided by `pytest-tornasync`) is used to make asynchronous HTTP requests to the test server. Tests are defined as native Python `async def` functions."},"warnings":[{"fix":"Ensure your project uses Tornado 5.0+ and Python 3.5+ (or newer compatible versions). Review your `requirements.txt` or `pyproject.toml` to ensure correct version pinning.","message":"pytest-tornasync requires Tornado version 5.0 or newer and Python 3.5+. Older versions of Tornado or Python will not be supported and may lead to unexpected errors or incompatible behavior.","severity":"breaking","affected_versions":"<=0.5.x"},{"fix":"Always define an `app` fixture in your `conftest.py` or test file, returning an instance of your `tornado.web.Application`. Example: `@pytest.fixture \\ndef app(): \\n    return your_app.make_app()`.","message":"The plugin automatically discovers fixtures. However, if the `app` fixture, which returns a `tornado.web.Application` instance, is not defined in your test suite, `pytest-tornasync` will raise a `FixtureLookupError: tornado application fixture not found` during test collection.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Remove `@pytest.mark.gen_test` from your async test functions when using `pytest-tornasync`. Simply define your tests as `async def test_something(...)`.","message":"Unlike `pytest-tornado`, `pytest-tornasync` is designed for plain native coroutine tests and does *not* require (or use) the `@pytest.mark.gen_test` decorator. Applying it might lead to unexpected behavior or redundant processing, as it is intended for a different async testing pattern.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Ensure all async operations are properly `await`ed or managed. Use `pytest --timeout=N` or `pytest-asyncio`'s timeout features if you suspect long-running or stuck coroutines. Check for resource deadlocks or unclosed connections.","message":"Async tests, especially those involving I/O or external services, can sometimes hang if the event loop is not correctly managed or if there are unhandled futures/tasks. This can manifest as `pytest` appearing to freeze indefinitely.","severity":"gotcha","affected_versions":"All versions"}],"env_vars":null,"last_verified":"2026-04-16T00:00:00.000Z","next_check":"2026-07-15T00:00:00.000Z","problems":[{"fix":"Create a fixture named `app` that returns your `tornado.web.Application`. Place this fixture in `conftest.py` or directly in your test file.\n```python\nimport pytest\nimport tornado.web\n\n@pytest.fixture\ndef app():\n    # Your Tornado application setup\n    class MainHandler(tornado.web.RequestHandler):\n        def get(self):\n            self.write(\"Hello\")\n    return tornado.web.Application([(r\"/\", MainHandler)])\n```","cause":"The `pytest-tornasync` plugin could not find a pytest fixture named `app` that is expected to provide the `tornado.web.Application` instance for testing.","error":"FixtureLookupError: tornado application fixture not found"},{"fix":"Ensure your async test functions are properly defined with `async def` and receive the necessary fixtures (e.g., `io_loop`, `http_server_client`) provided by `pytest-tornasync` to operate within its managed event loop. Avoid explicit `asyncio.get_event_loop()` calls unless you are managing the loop lifecycle manually.","cause":"Your asynchronous Tornado test code is attempting to interact with the `asyncio` event loop (e.g., awaiting a future) outside of a running event loop context, or the event loop provided by `pytest-tornasync` is not being properly utilized.","error":"RuntimeError: No current event loop in thread 'Thread-X' (or similar errors related to asyncio event loop)"},{"fix":"Verify that `pytest-tornasync` is correctly installed (`pip show pytest-tornasync`). Ensure no conflicting async plugins (like an older `pytest-tornado` that expects `@gen_test`) are enabled. Restart your pytest session to ensure plugin discovery.","cause":"Pytest is not recognizing your `async def` test function as an asynchronous test that needs to be run by an async-aware plugin. This often happens if `pytest-tornasync` is not correctly installed or enabled, or if another plugin is interfering.","error":"TypeError: 'coroutine' object is not iterable (or similar errors when a test function is async but treated as sync)"}]}