-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathconftest.py
More file actions
154 lines (112 loc) · 4.58 KB
/
conftest.py
File metadata and controls
154 lines (112 loc) · 4.58 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
"""Shared fixtures for SDK integration tests.
Tests run against production. See www.hotdata.dev/api/README.md for the
contract — env vars, naming conventions, blast-radius rules.
"""
from __future__ import annotations
import os
import uuid
from dataclasses import dataclass
from typing import Iterator
import pytest
from hotdata import ApiClient, Configuration
from hotdata.api.connections_api import ConnectionsApi
from hotdata.api.databases_api import DatabasesApi
from hotdata.api.datasets_api import DatasetsApi
from hotdata.api.indexes_api import IndexesApi
from hotdata.api.saved_queries_api import SavedQueriesApi
from hotdata.api.secrets_api import SecretsApi
from hotdata.api.workspaces_api import WorkspacesApi
from hotdata.models.create_database_request import CreateDatabaseRequest
REQUIRED_ENV = ("HOTDATA_SDK_TEST_API_KEY", "HOTDATA_SDK_TEST_WORKSPACE_ID")
DEFAULT_API_URL = "https://api.hotdata.dev"
# Queries are scoped to a database via the X-Database-Id header. Databases no
# longer auto-expire, so rather than create one per run (which would leak),
# tests find-or-create a single stable database by name and reuse it — same
# pattern as the e2e suite. Name is not unique server-side; we key off it.
SHARED_DATABASE_NAME = "sdkci-shared"
@dataclass(frozen=True)
class TestEnv:
api_url: str
api_key: str
workspace_id: str
connection_id: str | None
def _load_env() -> TestEnv:
missing = [name for name in REQUIRED_ENV if not os.environ.get(name)]
if missing:
pytest.skip(
"SDK integration tests require env vars: " + ", ".join(missing)
)
# GitHub Actions sets `env:` keys even when the underlying secret/var is
# unset, producing empty strings rather than absent keys. Use `or` to fall
# back to the default for url and to None for the optional connection id.
return TestEnv(
api_url=os.environ.get("HOTDATA_SDK_TEST_API_URL") or DEFAULT_API_URL,
api_key=os.environ["HOTDATA_SDK_TEST_API_KEY"],
workspace_id=os.environ["HOTDATA_SDK_TEST_WORKSPACE_ID"],
connection_id=os.environ.get("HOTDATA_SDK_TEST_CONNECTION_ID") or None,
)
@pytest.fixture(scope="session")
def env() -> TestEnv:
return _load_env()
@pytest.fixture(scope="session")
def api_client(env: TestEnv) -> Iterator[ApiClient]:
config = Configuration(
host=env.api_url,
api_key=env.api_key,
workspace_id=env.workspace_id,
)
with ApiClient(config) as client:
yield client
@pytest.fixture(scope="session")
def workspace_id(env: TestEnv) -> str:
return env.workspace_id
@pytest.fixture(scope="session")
def connection_id(env: TestEnv) -> str:
if not env.connection_id:
pytest.skip("HOTDATA_SDK_TEST_CONNECTION_ID required for this scenario")
return env.connection_id
@pytest.fixture(scope="session")
def database_id(api_client: ApiClient) -> str:
"""Id of the shared `sdkci-shared` database, creating it if absent.
Queries require an `X-Database-Id` scope; databases persist (no auto-expiry)
so we reuse one across runs instead of creating-and-deleting per session.
"""
databases_api = DatabasesApi(api_client)
for db in databases_api.list_databases().databases:
if db.name == SHARED_DATABASE_NAME:
return db.id
created = databases_api.create_database(
CreateDatabaseRequest(name=SHARED_DATABASE_NAME)
)
return created.id
@pytest.fixture
def sdkci_name() -> "callable[[str], str]":
"""Returns `sdkci-<scenario>-<uuid8>` so orphans are identifiable.
See api/README.md — every test-created resource must use this prefix.
"""
def _make(scenario: str) -> str:
return f"sdkci-{scenario}-{uuid.uuid4().hex[:8]}"
return _make
# Per-API client fixtures keep tests one-liner short and avoid every test
# instantiating its own *Api(api_client).
@pytest.fixture
def datasets_api(api_client: ApiClient) -> DatasetsApi:
return DatasetsApi(api_client)
@pytest.fixture
def workspaces_api(api_client: ApiClient) -> WorkspacesApi:
return WorkspacesApi(api_client)
@pytest.fixture
def connections_api(api_client: ApiClient) -> ConnectionsApi:
return ConnectionsApi(api_client)
@pytest.fixture
def databases_api(api_client: ApiClient) -> DatabasesApi:
return DatabasesApi(api_client)
@pytest.fixture
def indexes_api(api_client: ApiClient) -> IndexesApi:
return IndexesApi(api_client)
@pytest.fixture
def saved_queries_api(api_client: ApiClient) -> SavedQueriesApi:
return SavedQueriesApi(api_client)
@pytest.fixture
def secrets_api(api_client: ApiClient) -> SecretsApi:
return SecretsApi(api_client)