Skip to content

Commit c4b5e9a

Browse files
committed
Elementary OpenAPI integration tests
1 parent 2e39274 commit c4b5e9a

File tree

1 file changed

+90
-0
lines changed

1 file changed

+90
-0
lines changed
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
import json
2+
import os
3+
from pathlib import Path
4+
import typing as t
5+
6+
import pytest
7+
8+
# Strategy:
9+
# - Load the OpenAPI document from docs/openapi.json
10+
# - Validate critical structure based on the PR diff:
11+
# * openapi version, info, servers
12+
# * presence of paths/methods and key response codes
13+
# * presence and key attributes of important component schemas (enums, required fields)
14+
15+
OPENAPI_FILE = "docs/openapi.json"
16+
17+
18+
def _load_openapi_spec() -> dict:
19+
"""Load OpenAPI specification from configured path."""
20+
path = Path(OPENAPI_FILE)
21+
if path.is_file():
22+
with path.open("r", encoding="utf-8") as f:
23+
return json.load(f)
24+
25+
pytest.fail("OpenAPI spec not found")
26+
27+
28+
@pytest.fixture(scope="module")
29+
def spec() -> dict:
30+
"""Fixture containing OpenAPI specification represented as a dictionary."""
31+
return _load_openapi_spec()
32+
33+
34+
def test_openapi_top_level_info(spec: dict):
35+
"""Test all top level informations stored in OpenAPI specification."""
36+
assert spec.get("openapi") == "3.1.0"
37+
38+
info = spec.get("info") or {}
39+
assert info.get("title") == "Lightspeed Core Service (LCS) service - OpenAPI"
40+
assert "version" in info
41+
42+
contact = info.get("contact") or {}
43+
assert contact is not None
44+
45+
license = info.get("license") or {}
46+
assert license.get("name") == "Apache 2.0"
47+
assert "apache.org/licenses" in (license.get("url") or "")
48+
49+
50+
def test_servers_section_present(spec: dict):
51+
"""Test the servers section stored in OpenAPI specification."""
52+
servers = spec.get("servers")
53+
assert isinstance(servers, list) and servers, "servers must be a non-empty list"
54+
55+
56+
@pytest.mark.parametrize(
57+
"path,method,expected_codes",
58+
[
59+
("/", "get", {"200"}),
60+
("/v1/info", "get", {"200", "500"}),
61+
("/v1/models", "get", {"200", "503"}),
62+
("/v1/query", "post", {"200", "400", "403", "503", "422"}),
63+
("/v1/streaming_query", "post", {"200", "422"}),
64+
("/v1/config", "get", {"200", "503"}),
65+
("/v1/feedback", "post", {"200", "401", "403", "500", "422"}),
66+
("/v1/feedback/status", "get", {"200"}),
67+
("/v1/feedback/status", "put", {"200", "422"}),
68+
("/v1/conversations", "get", {"200", "503"}),
69+
("/v1/conversations/{conversation_id}", "get", {"200", "404", "503", "422"}),
70+
("/v1/conversations/{conversation_id}", "delete", {"200", "404", "503", "422"}),
71+
("/readiness", "get", {"200", "503"}),
72+
("/liveness", "get", {"200", "503"}),
73+
("/authorized", "post", {"200", "400", "403"}),
74+
("/metrics", "get", {"200"}),
75+
],
76+
)
77+
def test_paths_and_responses_exist(
78+
spec: dict, path: str, method: str, expected_codes: t.Set[str]
79+
):
80+
"""Tests all paths defined in OpenAPI specification."""
81+
paths = spec.get("paths") or {}
82+
assert path in paths, f"Missing path: {path}"
83+
op = (paths[path] or {}).get(method)
84+
assert isinstance(op, dict), f"Missing method {method.upper()} for path {path}"
85+
responses = op.get("responses") or {}
86+
got_codes = set(responses.keys())
87+
for code in expected_codes:
88+
assert (
89+
code in got_codes
90+
), f"Missing response code {code} for {method.upper()} {path}"

0 commit comments

Comments
 (0)