テスト#
Quartはグローバル変数(requestなど)を使用するため、これらの変数を使用するコードのテストが難しくなります。これを解決するために、Quartで直接呼び出されるコード(例:ルート関数またはリクエスト前関数)でのみこれらの変数を使用することをベストプラクティスとしています。その後、Quartはこれらのグローバル変数を制御するためのテストフレームワークを提供します。
主に、テスト対象のQuartアプリにバインドされたテストクライアントを使用してテストを行う必要があります。これは非常に一般的であるため、バインドされたクライアントを返すヘルパーメソッドtest_client()があります。例:
async def test_app(app):
client = app.test_client()
response = await client.get('/')
assert response.status_code == 200
イベントループ#
Quartでテストするには、非同期関数を呼び出すためにイベントループが必要です。これは手動で行うことができます。例:
def aiotest(func):
loop = asyncio.get_event_loop()
loop.run_until_complete(func())
@aiotest
async def test_app(app)
...
しかし、pytest-asyncioを使用する方がはるかに簡単です。 pytestは推奨されるテストランナーであり、以降の例ではpytestがpytest-asyncioと共に使用されていることを前提としています。
ルートの呼び出し#
テストクライアントには、すべてのHTTP動詞(例:post())のヘルパーメソッドがあります。これらはopen()のヘルパーメソッドであるため、すべてのメソッドは最低限パスを期待し、オプションでクエリパラメータ、JSONデータ、またはフォームデータを持つことができます。標準のResponseクラスが返されます。例:
async def test_create(app):
test_client = app.test_client()
data = {'name': 'foo'}
response = await test_client.post('/resource/', json=data)
assert response.status_code == 201
result = await response.get_json()
assert result == data
リクエストまたはレスポンスをストリーミングするルートをテストするには、request()メソッドを使用します。
async def test_stream() -> None:
test_client = app.test_client()
async with test_client.request(...) as connection:
await connection.send(b"data")
await connection.send_complete()
...
# receive a chunk of the response
data = await connection.receive()
...
# assemble the rest of the response without the first bit
response = await connection.as_response()
リクエストとレスポンスのストリーミングの詳細については、リクエストボディの消費とストリーミングレスポンスを参照してください。
コンテキストテスト#
アプリコンテキストまたはリクエストコンテキスト内で何かをテストする必要があることがよくあります。アプリコンテキストについては非常に簡単です。
async def test_app_context(app):
async with app.app_context():
current_app.[use]
ただし、リクエストコンテキストの場合、リクエストコンテキストを偽装する必要があります。最低限、メソッドとパスを指定する必要があります。例:
async def test_app_context(app):
async with app.test_request_context("/", method="GET"):
request.[use]
注記
before_request関数またはafter_request関数は、test_request_contextを使用している場合は呼び出されません。before_request関数が呼び出されるようにするには、await app.preprocess_request()を追加できます。
async def test_app_context(app):
async with app.test_request_context("/", method="GET"):
await app.preprocess_request()
# The before_request functions have now been called
request.[use]