Skip to content

Commit c4a6bca

Browse files
author
Jeny Sadadia
committed
tests/e2e_tests: drop synchronous test client
Due to `fastapi` version change, the newer `TestClient` from `fastapi` is causing issues by creating its own different event loop. That conflicts with the event loop of database client created in the app startup handler. Fix the below error by using async test client for all the tests: ``` @pytest.fixture(scope='session') def test_client(): """Fixture to get FastAPI Test client instance""" with TestClient(app=versioned_app, base_url=BASE_URL) as client: tests/e2e_tests/conftest.py:36: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ api/main.py:87: in initialize_beanie await db.initialize_beanie() api/db.py:51: in initialize_beanie await init_beanie( .local/lib/python3.11/site-packages/beanie/odm/utils/init.py:750: in init_beanie await Initializer( .local/lib/python3.11/site-packages/beanie/odm/utils/init.py:128: in __await__ yield from self.init_class(model).__await__() .local/lib/python3.11/site-packages/beanie/odm/utils/init.py:713: in init_class await self.init_document(cls) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = <beanie.odm.utils.init.Initializer object at 0x7457d1843cd0> cls = <class 'api.models.User'> > build_info = await self.database.command({"buildInfo": 1}) E RuntimeError: Task <Task pending name='anyio.from_thread.BlockingPortal._call_func' coro=<BlockingPortal._call_func() running at /home/kernelci/.local/lib/python3.11/site-packages/anyio/from_thread.py:217> cb=[TaskGroup._spawn.<locals>.task_done() at /home/kernelci/.local/lib/python3.11/site-packages/anyio/_backends/_asyncio.py:699]> got Future <Future pending cb=[_chain_future.<locals>._call_check_cancel() at /usr/local/lib/python3.11/asyncio/futures.py:387]> attached to a different loop .local/lib/python3.11/site-packages/beanie/odm/utils/init.py:545: RuntimeError ``` Signed-off-by: Jeny Sadadia <jeny.sadadia@collabora.com>
1 parent f55436a commit c4a6bca

6 files changed

+32
-28
lines changed

tests/e2e_tests/conftest.py

-8
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,6 @@
1010
from httpx import AsyncClient
1111
from motor.motor_asyncio import AsyncIOMotorClient
1212

13-
from fastapi.testclient import TestClient
14-
1513
from api.main import versioned_app
1614
from kernelci.api.models import Node, Regression
1715

@@ -30,12 +28,6 @@
3028
'offset',
3129
}
3230

33-
@pytest.fixture(scope='session')
34-
def test_client():
35-
"""Fixture to get FastAPI Test client instance"""
36-
with TestClient(app=versioned_app, base_url=BASE_URL) as client:
37-
yield client
38-
3931

4032
@pytest.fixture(scope='session')
4133
async def test_async_client():

tests/e2e_tests/test_count_handler.py

+6-4
Original file line numberDiff line numberDiff line change
@@ -10,33 +10,35 @@
1010
import pytest
1111

1212

13+
@pytest.mark.asyncio
1314
@pytest.mark.dependency(
1415
depends=[
1516
'tests/e2e_tests/test_pipeline.py::test_node_pipeline'],
1617
scope='session')
17-
def test_count_nodes(test_client):
18+
async def test_count_nodes(test_async_client):
1819
"""
1920
Test Case : Test KernelCI API GET /count endpoint
2021
Expected Result :
2122
HTTP Response Code 200 OK
2223
Total number of nodes available
2324
"""
24-
response = test_client.get("count")
25+
response = await test_async_client.get("count")
2526
assert response.status_code == 200
2627
assert response.json() >= 0
2728

2829

30+
@pytest.mark.asyncio
2931
@pytest.mark.dependency(
3032
depends=[
3133
'tests/e2e_tests/test_pipeline.py::test_node_pipeline'],
3234
scope='session')
33-
def test_count_nodes_matching_attributes(test_client):
35+
async def test_count_nodes_matching_attributes(test_async_client):
3436
"""
3537
Test Case : Test KernelCI API GET /count endpoint with attributes
3638
Expected Result :
3739
HTTP Response Code 200 OK
3840
Number of nodes matching attributes
3941
"""
40-
response = test_client.get("count?name=checkout")
42+
response = await test_async_client.get("count?name=checkout")
4143
assert response.status_code == 200
4244
assert response.json() >= 0

tests/e2e_tests/test_root_handler.py

+5-2
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,12 @@
55

66
"""End-to-end test functions for KernelCI API root handler"""
77

8+
import pytest
89

9-
def test_root_endpoint(test_client):
10+
11+
@pytest.mark.asyncio
12+
async def test_root_endpoint(test_async_client):
1013
"""Test root handler"""
11-
response = test_client.get("/latest")
14+
response = await test_async_client.get("/")
1215
assert response.status_code == 200
1316
assert response.json() == {"message": "KernelCI API"}

tests/e2e_tests/test_subscribe_handler.py

+9-6
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,19 @@
99
import pytest
1010

1111

12+
@pytest.mark.asyncio
1213
@pytest.mark.dependency(
1314
depends=['tests/e2e_tests/test_user_creation.py::test_create_regular_user'],
1415
scope='session')
1516
@pytest.mark.order(3)
16-
def test_subscribe_node_channel(test_client):
17+
async def test_subscribe_node_channel(test_async_client):
1718
"""
1819
Test Case : Test KernelCI API '/subscribe' endpoint with 'node' channel
1920
Expected Result :
2021
HTTP Response Code 200 OK
2122
JSON with subscription 'id' and 'channel' keys
2223
"""
23-
response = test_client.post(
24+
response = await test_async_client.post(
2425
"subscribe/node",
2526
headers={
2627
"Authorization": f"Bearer {pytest.BEARER_TOKEN}" # pylint: disable=no-member
@@ -32,18 +33,19 @@ def test_subscribe_node_channel(test_client):
3233
assert response.json().get('channel') == 'node'
3334

3435

36+
@pytest.mark.asyncio
3537
@pytest.mark.dependency(
3638
depends=['tests/e2e_tests/test_user_creation.py::test_create_regular_user'],
3739
scope='session')
3840
@pytest.mark.order(3)
39-
def test_subscribe_test_channel(test_client):
41+
async def test_subscribe_test_channel(test_async_client):
4042
"""
4143
Test Case : Test KernelCI API '/subscribe' endpoint with 'test_channel'
4244
Expected Result :
4345
HTTP Response Code 200 OK
4446
JSON with subscription 'id' and 'channel' keys
4547
"""
46-
response = test_client.post(
48+
response = await test_async_client.post(
4749
"subscribe/test_channel",
4850
headers={
4951
"Authorization": f"Bearer {pytest.BEARER_TOKEN}" # pylint: disable=no-member
@@ -55,19 +57,20 @@ def test_subscribe_test_channel(test_client):
5557
assert response.json().get('channel') == 'test_channel'
5658

5759

60+
@pytest.mark.asyncio
5861
@pytest.mark.dependency(
5962
depends=['tests/e2e_tests/test_user_creation.py::test_create_regular_user'],
6063
scope='session')
6164
@pytest.mark.order(3)
62-
def test_subscribe_user_group_channel(test_client):
65+
async def test_subscribe_user_group_channel(test_async_client):
6366
"""
6467
Test Case : Test KernelCI API '/subscribe' endpoint with 'user_group'
6568
channel
6669
Expected Result :
6770
HTTP Response Code 200 OK
6871
JSON with subscription 'id' and 'channel' keys
6972
"""
70-
response = test_client.post(
73+
response = await test_async_client.post(
7174
"subscribe/user_group",
7275
headers={
7376
"Authorization": f"Bearer {pytest.BEARER_TOKEN}" # pylint: disable=no-member

tests/e2e_tests/test_unsubscribe_handler.py

+6-4
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,19 @@
99
import pytest
1010

1111

12+
@pytest.mark.asyncio
1213
@pytest.mark.dependency(
1314
depends=[
1415
'tests/e2e_tests/test_subscribe_handler.py::test_subscribe_node_channel'],
1516
scope='session')
1617
@pytest.mark.order("last")
17-
def test_unsubscribe_node_channel(test_client):
18+
async def test_unsubscribe_node_channel(test_async_client):
1819
"""
1920
Test Case : Test KernelCI API '/unsubscribe' endpoint with 'node' channel
2021
Expected Result :
2122
HTTP Response Code 200 OK
2223
"""
23-
response = test_client.post(
24+
response = await test_async_client.post(
2425
f"unsubscribe/{pytest.node_channel_subscription_id}", # pylint: disable=no-member
2526
headers={
2627
"Authorization": f"Bearer {pytest.BEARER_TOKEN}" # pylint: disable=no-member
@@ -29,18 +30,19 @@ def test_unsubscribe_node_channel(test_client):
2930
assert response.status_code == 200
3031

3132

33+
@pytest.mark.asyncio
3234
@pytest.mark.dependency(
3335
depends=[
3436
'tests/e2e_tests/test_subscribe_handler.py::test_subscribe_test_channel'],
3537
scope='session')
3638
@pytest.mark.order("last")
37-
def test_unsubscribe_test_channel(test_client):
39+
async def test_unsubscribe_test_channel(test_async_client):
3840
"""
3941
Test Case : Test KernelCI API '/unsubscribe' endpoint with 'test_channel'
4042
Expected Result :
4143
HTTP Response Code 200 OK
4244
"""
43-
response = test_client.post(
45+
response = await test_async_client.post(
4446
f"unsubscribe/{pytest.test_channel_subscription_id}", # pylint: disable=no-member
4547
headers={
4648
"Authorization": f"Bearer {pytest.BEARER_TOKEN}" # pylint: disable=no-member

tests/e2e_tests/test_user_creation.py

+6-4
Original file line numberDiff line numberDiff line change
@@ -118,16 +118,17 @@ async def test_create_regular_user(test_async_client):
118118
pytest.BEARER_TOKEN = response.json()['access_token']
119119

120120

121+
@pytest.mark.asyncio
121122
@pytest.mark.dependency(depends=["test_create_regular_user"])
122-
def test_whoami(test_client):
123+
async def test_whoami(test_async_client):
123124
"""
124125
Test Case : Test KernelCI API /whoami endpoint
125126
Expected Result :
126127
HTTP Response Code 200 OK
127128
JSON with 'id', 'email', username', 'groups', 'is_superuser'
128129
'is_verified' and 'is_active' keys
129130
"""
130-
response = test_client.get(
131+
response = await test_async_client.get(
131132
"whoami",
132133
headers={
133134
"Accept": "application/json",
@@ -140,16 +141,17 @@ def test_whoami(test_client):
140141
assert response.json()['username'] == 'test_user'
141142

142143

144+
@pytest.mark.asyncio
143145
@pytest.mark.dependency(depends=["test_create_regular_user"])
144-
def test_create_user_negative(test_client):
146+
async def test_create_user_negative(test_async_client):
145147
"""
146148
Test Case : Test KernelCI API /user/register endpoint when requested
147149
with regular user's bearer token.
148150
Expected Result :
149151
HTTP Response Code 403 Forbidden
150152
JSON with 'detail' key denoting 'Forbidden' error
151153
"""
152-
response = test_client.post(
154+
response = await test_async_client.post(
153155
"user/register",
154156
headers={
155157
"Accept": "application/json",

0 commit comments

Comments
 (0)