Skip to content

Commit

Permalink
Property parameterize test entities for test runs
Browse files Browse the repository at this point in the history
  • Loading branch information
CasperWA committed Nov 22, 2023
1 parent c5d5742 commit 8f2c7e6
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 69 deletions.
1 change: 1 addition & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -67,3 +67,4 @@ repos:
- pydantic>=2
- types-requests
- types-pyyaml
args: [--explicit-package-bases]
42 changes: 0 additions & 42 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,7 @@
import pytest

if TYPE_CHECKING:
from collections.abc import Callable
from pathlib import Path
from typing import Any

from fastapi.testclient import TestClient
from pymongo.collection import Collection
Expand Down Expand Up @@ -60,46 +58,6 @@ def _mock_backend_entities_collection(
monkeypatch.setattr(backend, "ENTITIES_COLLECTION", mongo_test_collection)


@pytest.fixture()
def get_version_name() -> Callable[[str], tuple[str, str]]:
"""Return the version and name part of a uri."""
import re

def _get_version_name(uri: str) -> tuple[str, str]:
"""Return the version and name part of a uri."""
match = re.match(
r"^http://onto-ns\.com/meta/(?P<version>[^/]+)/(?P<name>[^/]+)$", uri
)
assert match is not None, (
f"Could not retrieve version and name from {uri!r}. "
"URI must be of the form: "
"http://onto-ns.com/meta/{version}/{name}"
)

return match.group("version") or "", match.group("name") or ""

return _get_version_name


@pytest.fixture()
def get_uri() -> Callable[[dict[str, Any]], str]:
"""Return the uri for an entity."""

def _get_uri(entity: dict[str, Any]) -> str:
"""Return the uri for an entity."""
namespace = entity.get("namespace")
version = entity.get("version")
name = entity.get("name")

assert not any(
_ is None for _ in (namespace, version, name)
), "Could not retrieve namespace, version, and/or name from test entities."

return f"{namespace}/{version}/{name}"

return _get_uri


@pytest.fixture()
def client() -> TestClient:
"""Return the test client."""
Expand Down
67 changes: 40 additions & 27 deletions tests/test_route.py
Original file line number Diff line number Diff line change
@@ -1,51 +1,64 @@
"""Test the service's only route to retrieve DLite/SOFT entities."""
from __future__ import annotations

import sys
from typing import TYPE_CHECKING

import pytest

from tests.utils import parameterize_get_entities

if TYPE_CHECKING:
from collections.abc import Callable
from pathlib import Path
from typing import Any

from fastapi.testclient import TestClient


@pytest.mark.parametrize(
("entity", "version", "name"),
parameterize_get_entities(),
ids=[f"{_.version}/{_.name}" for _ in parameterize_get_entities()],
)
def test_get_entity(
static_dir: Path,
get_version_name: Callable[[str], tuple[str, str]],
get_uri: Callable[[dict[str, Any]], str],
entity: dict[str, Any],
version: str,
name: str,
client: TestClient,
) -> None:
"""Test the route to retrieve a DLite/SOFT entity."""
import sys

import yaml
from fastapi import status

entities: list[dict[str, Any]] = yaml.safe_load(
(static_dir / "entities.yaml").read_text()
)

for entity in entities:
uri = entity.get("uri") or get_uri(entity)

version, name = get_version_name(uri)
response = client.get(f"/{version}/{name}", timeout=5)

response = client.get(f"/{version}/{name}", timeout=5)
assert (
response.is_success
), f"Response: {response.json()}. Request: {response.request}"
assert response.status_code == status.HTTP_200_OK, response.json()
assert (resolved_entity := response.json()) == entity, resolved_entity


@pytest.mark.skipif(
sys.version_info >= (3, 12), reason="DLite does not yet support Python 3.12+."
)
@pytest.mark.parametrize(
("entity", "version", "name"),
parameterize_get_entities(),
ids=[f"{_.version}/{_.name}" for _ in parameterize_get_entities()],
)
def test_get_entity_instance(
entity: dict[str, Any],
version: str,
name: str,
client: TestClient,
) -> None:
"""Validate that we can instantiate an Instance from the response"""
from dlite import Instance

assert (
response.is_success
), f"Response: {response.json()}. Request: {response.request}"
assert response.status_code == status.HTTP_200_OK, response.json()
assert (resolved_entity := response.json()) == entity, resolved_entity
response = client.get(f"/{version}/{name}", timeout=5)

# Validate that we can instantiate an Instance from the response
# DLite does not support Python 3.12 yet.
if sys.version_info < (3, 12):
from dlite import Instance
assert (resolve_entity := response.json()) == entity, resolve_entity

Instance.from_dict(resolved_entity)
Instance.from_dict(resolve_entity)


def test_get_entity_not_found(client: TestClient) -> None:
Expand Down
72 changes: 72 additions & 0 deletions tests/utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
"""Utility functions for tests."""
from __future__ import annotations

from typing import TYPE_CHECKING, NamedTuple

if TYPE_CHECKING:
from typing import Any


class ParameterizeGetEntities(NamedTuple):
"""Returned tuple from parameterizing all entities."""

entity: dict[str, Any]
version: str
name: str


def get_version_name(uri: str) -> tuple[str, str]:
"""Return the version and name part of a uri."""
import re

from dlite_entities_service.config import CONFIG

namespace = str(CONFIG.base_url).rstrip("/")

match = re.match(
rf"^{re.escape(namespace)}/(?P<version>[^/]+)/(?P<name>[^/]+)$", uri
)
assert match is not None, (
f"Could not retrieve version and name from {uri!r}. "
"URI must be of the form: "
"http://onto-ns.com/meta/{version}/{name}"
)

return match.group("version") or "", match.group("name") or ""


def get_uri(entity: dict[str, Any]) -> str:
"""Return the uri for an entity."""
namespace = entity.get("namespace")
version = entity.get("version")
name = entity.get("name")

assert not any(
_ is None for _ in (namespace, version, name)
), "Could not retrieve namespace, version, and/or name from test entities."

return f"{namespace}/{version}/{name}"


def parameterize_get_entities() -> list[ParameterizeGetEntities]:
"""Parameterize the test to retrieve all entities."""
from pathlib import Path

import yaml

static_dir = (Path(__file__).parent / "static").resolve()

results: list[ParameterizeGetEntities] = []

entities: list[dict[str, Any]] = yaml.safe_load(
(static_dir / "entities.yaml").read_text()
)

for entity in entities:
uri = entity.get("uri") or get_uri(entity)

version, name = get_version_name(uri)

results.append(ParameterizeGetEntities(entity, version, name))

return results

0 comments on commit 8f2c7e6

Please sign in to comment.