Issue
Normally, when testing an endpoint, the Flask docs recommend doing something like this:
import pytest
from my_project import create_app
@pytest.fixture()
def app():
app = create_app()
yield app
@pytest.fixture()
def client(app):
return app.test_client()
and then using the client
fixture in a test like so:
def test_ping(client):
response = client.get("/foobar")
assert response.status_code == 200
However, in some very niche cases, the code which handles the /foobar
endpoint might need to make a HTTP call back to the Flask server (imagine it imports a poorly-designed library which needs to fetch some data from an endpoint and it doesn't allow you to inject a custom fetcher, so all you can do is to specify a custom URL). How can I run the entire Flask server in a background thread?
Solution
For this purpose, it used to be possible to leverage the werkzeug.server.shutdown
mechanism. Unfortunately, this has been deprecated and removed.
However, this mechanism isn't strictly necessary. If you only need the server to start once before running the tests (at the session
level), then you can run it as a daemon
background thread and you can skip thread.join()
because, when the tests finish, it will be the only thread left running and the Python process exits when only daemon
threads are left. Details here. There is some potential for race conditions if the server doesn't get a chance to start before the tests execute, but that can be "fixed" with a bit of sleep...
This is the code ended up with in my conftest.py
:
@pytest.fixture(scope='session')
def app():
app = create_app()
thread = Thread(target=app.run, daemon=True, kwargs=dict(host='localhost', port=5000))
thread.start()
yield app
@pytest.fixture(scope='module')
def client(app):
return app.test_client()
All the tests which need this full-fledged Flask server to be up and running must to use the client
fixture which depends on the app
fixture.
Answered By - Mihai Todor
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.