Skip to content

Commit

Permalink
Use a httpx.client interface for calling the php server
Browse files Browse the repository at this point in the history
This puts the configuration in one place (the fixture) and makes
it easier to add new calls / understand where the calls go.
  • Loading branch information
PGijsbers committed Nov 28, 2023
1 parent 3d1ccc0 commit 33b6e42
Show file tree
Hide file tree
Showing 7 changed files with 105 additions and 88 deletions.
9 changes: 8 additions & 1 deletion tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from pathlib import Path
from typing import Any, Generator

import httpx
import pytest
from database.setup import expdb_database, user_database
from fastapi.testclient import TestClient
Expand Down Expand Up @@ -40,7 +41,13 @@ def user_test() -> Connection:


@pytest.fixture()
def api_client(expdb_test: Connection, user_test: Connection) -> TestClient:
def php_api() -> httpx.Client:
with httpx.Client(base_url="http://server-api-php-api-1:80/api/v1/json") as client:
yield client


@pytest.fixture()
def py_api(expdb_test: Connection, user_test: Connection) -> TestClient:
app = create_api()
# We use the lambda definitions because fixtures may not be called directly.
app.dependency_overrides[expdb_connection] = lambda: expdb_test
Expand Down
20 changes: 10 additions & 10 deletions tests/routers/openml/dataset_tag_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@
[None, ApiKey.INVALID],
ids=["no authentication", "invalid key"],
)
def test_dataset_tag_rejects_unauthorized(key: ApiKey, api_client: TestClient) -> None:
def test_dataset_tag_rejects_unauthorized(key: ApiKey, py_api: TestClient) -> None:
apikey = "" if key is None else f"?api_key={key}"
response = cast(
httpx.Response,
api_client.post(
py_api.post(
f"/datasets/tag{apikey}",
json={"data_id": constants.PRIVATE_DATASET_ID, "tag": "test"},
),
Expand All @@ -34,11 +34,11 @@ def test_dataset_tag_rejects_unauthorized(key: ApiKey, api_client: TestClient) -
[ApiKey.ADMIN, ApiKey.REGULAR_USER, ApiKey.OWNER_USER],
ids=["administrator", "non-owner", "owner"],
)
def test_dataset_tag(key: ApiKey, expdb_test: Connection, api_client: TestClient) -> None:
def test_dataset_tag(key: ApiKey, expdb_test: Connection, py_api: TestClient) -> None:
dataset_id, tag = constants.PRIVATE_DATASET_ID, "test"
response = cast(
httpx.Response,
api_client.post(
py_api.post(
f"/datasets/tag?api_key={key}",
json={"data_id": dataset_id, "tag": tag},
),
Expand All @@ -50,11 +50,11 @@ def test_dataset_tag(key: ApiKey, expdb_test: Connection, api_client: TestClient
assert tag in tags


def test_dataset_tag_returns_existing_tags(api_client: TestClient) -> None:
def test_dataset_tag_returns_existing_tags(py_api: TestClient) -> None:
dataset_id, tag = 1, "test"
response = cast(
httpx.Response,
api_client.post(
py_api.post(
f"/datasets/tag?api_key={ApiKey.ADMIN}",
json={"data_id": dataset_id, "tag": tag},
),
Expand All @@ -63,11 +63,11 @@ def test_dataset_tag_returns_existing_tags(api_client: TestClient) -> None:
assert {"data_tag": {"id": str(dataset_id), "tag": ["study_14", tag]}} == response.json()


def test_dataset_tag_fails_if_tag_exists(api_client: TestClient) -> None:
def test_dataset_tag_fails_if_tag_exists(py_api: TestClient) -> None:
dataset_id, tag = 1, "study_14" # Dataset 1 already is tagged with 'study_14'
response = cast(
httpx.Response,
api_client.post(
py_api.post(
f"/datasets/tag?api_key={ApiKey.ADMIN}",
json={"data_id": dataset_id, "tag": tag},
),
Expand All @@ -90,11 +90,11 @@ def test_dataset_tag_fails_if_tag_exists(api_client: TestClient) -> None:
)
def test_dataset_tag_invalid_tag_is_rejected(
tag: str,
api_client: TestClient,
py_api: TestClient,
) -> None:
new = cast(
httpx.Response,
api_client.post(
py_api.post(
f"/datasets/tag?api_key{ApiKey.ADMIN}",
json={"data_id": 1, "tag": tag},
),
Expand Down
61 changes: 31 additions & 30 deletions tests/routers/openml/datasets_list_datasets_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ def _assert_empty_result(
assert response.json()["detail"] == {"code": "372", "message": "No results"}


def test_list(api_client: TestClient) -> None:
response = api_client.get("/datasets/list/")
def test_list(py_api: TestClient) -> None:
response = py_api.get("/datasets/list/")
assert response.status_code == http.client.OK
assert "data" in response.json()
assert "dataset" in response.json()["data"]
Expand All @@ -38,8 +38,8 @@ def test_list(api_client: TestClient) -> None:
("all", constants.NUMBER_OF_DATASETS - constants.NUMBER_OF_PRIVATE_DATASETS),
],
)
def test_list_filter_active(status: str, amount: int, api_client: TestClient) -> None:
response = api_client.post(
def test_list_filter_active(status: str, amount: int, py_api: TestClient) -> None:
response = py_api.post(
"/datasets/list",
json={"status": status, "pagination": {"limit": constants.NUMBER_OF_DATASETS}},
)
Expand All @@ -57,9 +57,9 @@ def test_list_filter_active(status: str, amount: int, api_client: TestClient) ->
(None, constants.NUMBER_OF_DATASETS - constants.NUMBER_OF_PRIVATE_DATASETS),
],
)
def test_list_accounts_privacy(api_key: ApiKey | None, amount: int, api_client: TestClient) -> None:
def test_list_accounts_privacy(api_key: ApiKey | None, amount: int, py_api: TestClient) -> None:
key = f"?api_key={api_key}" if api_key else ""
response = api_client.post(
response = py_api.post(
f"/datasets/list{key}",
json={"status": "all", "pagination": {"limit": 1000}},
)
Expand All @@ -72,9 +72,9 @@ def test_list_accounts_privacy(api_key: ApiKey | None, amount: int, api_client:
("name", "count"),
[("abalone", 1), ("iris", 2)],
)
def test_list_data_name_present(name: str, count: int, api_client: TestClient) -> None:
def test_list_data_name_present(name: str, count: int, py_api: TestClient) -> None:
# The second iris dataset is private, so we need to authenticate.
response = api_client.post(
response = py_api.post(
f"/datasets/list?api_key={ApiKey.ADMIN}",
json={"status": "all", "data_name": name},
)
Expand All @@ -88,8 +88,8 @@ def test_list_data_name_present(name: str, count: int, api_client: TestClient) -
"name",
["ir", "long_name_without_overlap"],
)
def test_list_data_name_absent(name: str, api_client: TestClient) -> None:
response = api_client.post(
def test_list_data_name_absent(name: str, py_api: TestClient) -> None:
response = py_api.post(
f"/datasets/list?api_key={ApiKey.ADMIN}",
json={"status": "all", "data_name": name},
)
Expand All @@ -102,7 +102,7 @@ def test_list_quality_filers() -> None:

@pytest.mark.parametrize("limit", [None, 5, 10, 200])
@pytest.mark.parametrize("offset", [None, 0, 5, 129, 130, 200])
def test_list_pagination(limit: int | None, offset: int | None, api_client: TestClient) -> None:
def test_list_pagination(limit: int | None, offset: int | None, py_api: TestClient) -> None:
all_ids = [
did
for did in range(1, 1 + constants.NUMBER_OF_DATASETS)
Expand All @@ -116,7 +116,7 @@ def test_list_pagination(limit: int | None, offset: int | None, api_client: Test
offset_body = {} if offset is None else {"offset": offset}
limit_body = {} if limit is None else {"limit": limit}
filters = {"status": "all", "pagination": offset_body | limit_body}
response = api_client.post("/datasets/list", json=filters)
response = py_api.post("/datasets/list", json=filters)

if offset in [130, 200]:
_assert_empty_result(response)
Expand All @@ -131,8 +131,8 @@ def test_list_pagination(limit: int | None, offset: int | None, api_client: Test
("version", "count"),
[(1, 100), (2, 6), (5, 1)],
)
def test_list_data_version(version: int, count: int, api_client: TestClient) -> None:
response = api_client.post(
def test_list_data_version(version: int, count: int, py_api: TestClient) -> None:
response = py_api.post(
f"/datasets/list?api_key={ApiKey.ADMIN}",
json={"status": "all", "data_version": version},
)
Expand All @@ -142,8 +142,8 @@ def test_list_data_version(version: int, count: int, api_client: TestClient) ->
assert {dataset["version"] for dataset in datasets} == {version}


def test_list_data_version_no_result(api_client: TestClient) -> None:
response = api_client.post(
def test_list_data_version_no_result(py_api: TestClient) -> None:
response = py_api.post(
f"/datasets/list?api_key={ApiKey.ADMIN}",
json={"status": "all", "data_version": 4},
)
Expand All @@ -158,8 +158,8 @@ def test_list_data_version_no_result(api_client: TestClient) -> None:
("user_id", "count"),
[(1, 59), (2, 34), (16, 1)],
)
def test_list_uploader(user_id: int, count: int, key: str, api_client: TestClient) -> None:
response = api_client.post(
def test_list_uploader(user_id: int, count: int, key: str, py_api: TestClient) -> None:
response = py_api.post(
f"/datasets/list?api_key={key}",
json={"status": "all", "uploader": user_id},
)
Expand All @@ -177,8 +177,8 @@ def test_list_uploader(user_id: int, count: int, key: str, api_client: TestClien
"data_id",
[[1], [1, 2, 3], [1, 2, 3, 3000], [1, 2, 3, 130]],
)
def test_list_data_id(data_id: list[int], api_client: TestClient) -> None:
response = api_client.post(
def test_list_data_id(data_id: list[int], py_api: TestClient) -> None:
response = py_api.post(
"/datasets/list",
json={"status": "all", "data_id": data_id},
)
Expand All @@ -193,8 +193,8 @@ def test_list_data_id(data_id: list[int], api_client: TestClient) -> None:
("tag", "count"),
[("study_14", 100), ("study_15", 1)],
)
def test_list_data_tag(tag: str, count: int, api_client: TestClient) -> None:
response = api_client.post(
def test_list_data_tag(tag: str, count: int, py_api: TestClient) -> None:
response = py_api.post(
"/datasets/list",
# study_14 has 100 datasets, we overwrite the default `limit` because otherwise
# we don't know if the results are limited by filtering on the tag.
Expand All @@ -205,8 +205,8 @@ def test_list_data_tag(tag: str, count: int, api_client: TestClient) -> None:
assert len(datasets) == count


def test_list_data_tag_empty(api_client: TestClient) -> None:
response = api_client.post(
def test_list_data_tag_empty(py_api: TestClient) -> None:
response = py_api.post(
"/datasets/list",
json={"status": "all", "tag": "not-a-tag"},
)
Expand All @@ -226,8 +226,8 @@ def test_list_data_tag_empty(api_client: TestClient) -> None:
("number_missing_values", "2..100000", 22),
],
)
def test_list_data_quality(quality: str, range_: str, count: int, api_client: TestClient) -> None:
response = api_client.post(
def test_list_data_quality(quality: str, range_: str, count: int, py_api: TestClient) -> None:
response = py_api.post(
"/datasets/list",
json={"status": "all", quality: range_},
)
Expand Down Expand Up @@ -258,7 +258,8 @@ def test_list_data_quality(quality: str, range_: str, count: int, api_client: Te
api_key=st.sampled_from([None, ApiKey.REGULAR_USER, ApiKey.OWNER_USER]),
) # type: ignore[misc] # https://github.com/openml/server-api/issues/108
def test_list_data_identical(
api_client: TestClient,
py_api: TestClient,
php_api: httpx.Client,
**kwargs: dict[str, Any],
) -> Any:
limit, offset = kwargs["limit"], kwargs["offset"]
Expand All @@ -275,7 +276,7 @@ def test_list_data_identical(
if offset is not None:
new_style["pagination"]["offset"] = offset

response = api_client.post(
response = py_api.post(
f"/datasets/list{api_key_query}",
json=new_style,
)
Expand All @@ -286,11 +287,11 @@ def test_list_data_identical(
for filter_, value in kwargs.items()
if value is not None
]
uri = "http://server-api-php-api-1:80/api/v1/json/data/list"
uri = "/data/list"
if query:
uri += f"/{'/'.join([str(v) for q in query for v in q])}"
uri += api_key_query
original = httpx.get(uri)
original = php_api.get(uri)

assert original.status_code == response.status_code, response.json()
if original.status_code == http.client.PRECONDITION_FAILED:
Expand Down
16 changes: 8 additions & 8 deletions tests/routers/openml/datasets_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@
def test_error_unknown_dataset(
dataset_id: int,
response_code: int,
api_client: TestClient,
py_api: TestClient,
) -> None:
response = cast(httpx.Response, api_client.get(f"/datasets/{dataset_id}"))
response = cast(httpx.Response, py_api.get(f"/datasets/{dataset_id}"))

assert response.status_code == response_code
assert {"code": "111", "message": "Unknown dataset"} == response.json()["detail"]
Expand All @@ -33,28 +33,28 @@ def test_error_unknown_dataset(
],
)
def test_private_dataset_no_user_no_access(
api_client: TestClient,
py_api: TestClient,
api_key: str | None,
response_code: int,
) -> None:
query = f"?api_key={api_key}" if api_key else ""
response = cast(httpx.Response, api_client.get(f"/datasets/130{query}"))
response = cast(httpx.Response, py_api.get(f"/datasets/130{query}"))

assert response.status_code == response_code
assert {"code": "112", "message": "No access granted"} == response.json()["detail"]


@pytest.mark.skip("Not sure how to include apikey in test yet.")
def test_private_dataset_owner_access(
api_client: TestClient,
py_api: TestClient,
dataset_130: dict[str, Any],
) -> None:
response = cast(httpx.Response, api_client.get("/v2/datasets/130?api_key=..."))
response = cast(httpx.Response, py_api.get("/v2/datasets/130?api_key=..."))
assert response.status_code == http.client.OK
assert dataset_130 == response.json()


@pytest.mark.skip("Not sure how to include apikey in test yet.")
def test_private_dataset_admin_access(api_client: TestClient) -> None:
cast(httpx.Response, api_client.get("/v2/datasets/130?api_key=..."))
def test_private_dataset_admin_access(py_api: TestClient) -> None:
cast(httpx.Response, py_api.get("/v2/datasets/130?api_key=..."))
# test against cached response
Loading

0 comments on commit 33b6e42

Please sign in to comment.