Skip to content

Commit 5822553

Browse files
committed
test: reorganize static tests and expand config-based IO coverage
This commit restructures the static test setup and extends the test runner to cover split TOML configuration loading and merged config access. Included in this update: - move the static test module from tmp_tests to static_tests - add a dedicated static test package structure - expand the static IO test runner to write and merge multiple TOML files - add coverage for nested config access and merged configuration values - keep the JSON read and write flow as part of the static integration-style test run
1 parent fd999b0 commit 5822553

3 files changed

Lines changed: 222 additions & 107 deletions

File tree

tests/static_tests/static_test.py

Lines changed: 222 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,222 @@
1+
from __future__ import annotations
2+
3+
from pathlib import Path
4+
from typing import Any, Mapping
5+
from faker import Faker
6+
7+
from clevertools import configure, log, read_json, read_toml, write_json, write_toml
8+
from ..paths import PATHS
9+
10+
11+
def _deep_merge(base: dict[str, Any], incoming: Mapping[str, Any]) -> dict[str, Any]:
12+
for key, value in incoming.items():
13+
current = base.get(key)
14+
15+
if isinstance(current, dict) and isinstance(value, Mapping):
16+
base[key] = _deep_merge(dict(current), value)
17+
continue
18+
19+
if isinstance(value, Mapping):
20+
base[key] = _deep_merge({}, value)
21+
continue
22+
23+
base[key] = value
24+
25+
return base
26+
27+
28+
class ConfigView:
29+
def __init__(self, data: Mapping[str, Any]) -> None:
30+
self._data = dict(data)
31+
32+
def __getattr__(self, name: str) -> Any:
33+
try:
34+
value = self._data[name]
35+
except KeyError as exc:
36+
raise AttributeError(f"Config key not found: {name}") from exc
37+
return self._wrap(value)
38+
39+
def get(self, path: str, default: Any = None) -> Any:
40+
current: Any = self
41+
42+
for part in path.split("."):
43+
if not part:
44+
return default
45+
46+
if isinstance(current, ConfigView):
47+
if part not in current._data:
48+
return default
49+
current = current._data[part]
50+
current = self._wrap(current)
51+
continue
52+
53+
if isinstance(current, Mapping):
54+
if part not in current:
55+
return default
56+
current = current[part]
57+
continue
58+
59+
return default
60+
61+
return current
62+
63+
@staticmethod
64+
def _wrap(value: Any) -> Any:
65+
if isinstance(value, Mapping):
66+
return ConfigView(value)
67+
return value
68+
69+
70+
def load_config_files(*file_paths: Path | str) -> ConfigView:
71+
merged: dict[str, Any] = {}
72+
73+
for file_path in file_paths:
74+
loaded = read_toml(file_path, on_error="raise")
75+
if loaded is None:
76+
continue
77+
merged = _deep_merge(merged, loaded)
78+
79+
return ConfigView(merged)
80+
81+
82+
class StaticTestRunner:
83+
def __init__(self) -> None:
84+
self.fake = Faker("de_DE")
85+
self.tmp_settings_toml: Path = PATHS.CACHE_FOLDER / "settings.toml"
86+
self.tmp_content_toml: Path = PATHS.CACHE_FOLDER / "content.toml"
87+
self.tmp_json: Path = PATHS.CACHE_FOLDER / "users.json"
88+
89+
def configure_logger(self) -> None:
90+
configure(
91+
error_mode="log",
92+
logger_overrides={
93+
"name": "ClevertoolsStaticTest",
94+
"level": "INFO",
95+
"format_preset": "datetime",
96+
"file_logging_enabled": True,
97+
"file_log_path": PATHS.CACHE_FOLDER / "clevertools_static_test.log",
98+
"use_colors": True
99+
},
100+
)
101+
log.info("Logger configured for static IO test run.")
102+
103+
def build_settings_payload(self) -> dict[str, Any]:
104+
log.info("Building settings TOML payload for configuration test data.")
105+
payload = {
106+
"program": {
107+
"enviroment": "release",
108+
"wait_for_enter": True,
109+
},
110+
"logger": {
111+
"name": "ClevertoolsStaticTest",
112+
"level": "INFO",
113+
"format_preset": "datetime",
114+
"file_logging_enabled": True,
115+
"file_log_path": str(PATHS.CACHE_FOLDER / "clevertools_static_test.log"),
116+
},
117+
"pipelines": {
118+
"ai": {
119+
"enabled": True,
120+
"cleanup_temp": True,
121+
}
122+
},
123+
}
124+
log.info("Settings TOML payload prepared successfully.")
125+
return payload
126+
127+
def build_content_payload(self) -> dict[str, Any]:
128+
log.info("Building content TOML payload for configuration merge test.")
129+
payload = {
130+
"program": {
131+
"paths": [
132+
str(PATHS.CACHE_FOLDER / "hello"),
133+
str(PATHS.CACHE_FOLDER / "world"),
134+
str(PATHS.CACHE_FOLDER / "my"),
135+
str(PATHS.CACHE_FOLDER / "name"),
136+
str(PATHS.CACHE_FOLDER / "is"),
137+
str(PATHS.CACHE_FOLDER / "b7binw13"),
138+
str(PATHS.CACHE_FOLDER / "yayxD"),
139+
],
140+
},
141+
"pipelines": {
142+
"ai": {
143+
"ai_model": "gpt-oss:20B",
144+
"valid_local_ai_models": [
145+
"gpt-oss:20B",
146+
"mistral-small3.1:24b",
147+
],
148+
}
149+
},
150+
}
151+
log.info(f"Content TOML payload prepared with {len(payload['program']['paths'])} configured paths.")
152+
return payload
153+
154+
def generate_user(self) -> dict[str, Any]:
155+
return {
156+
"name": self.fake.name(),
157+
"email": self.fake.email(),
158+
"contacts": {
159+
self.fake.user_name(): {
160+
"nickname": self.fake.first_name(),
161+
"email": self.fake.email(),
162+
"phone": self.fake.phone_number(),
163+
}
164+
},
165+
}
166+
167+
def build_users_payload(self, count: int = 10) -> list[dict[str, Any]]:
168+
log.info(f"Generating JSON payload with {count} fake users.")
169+
users = [self.generate_user() for _ in range(count)]
170+
log.info(f"JSON payload prepared with {len(users)} generated users.")
171+
return users
172+
173+
def run(self) -> None:
174+
self.configure_logger()
175+
log.info("Starting static IO test run.")
176+
log.info(
177+
f"Using test files SETTINGS={self.tmp_settings_toml}, CONTENT={self.tmp_content_toml}, JSON={self.tmp_json}."
178+
)
179+
180+
settings_payload = self.build_settings_payload()
181+
content_payload = self.build_content_payload()
182+
users_payload = self.build_users_payload()
183+
184+
log.info(f"Writing settings TOML test data to {self.tmp_settings_toml}.")
185+
write_toml(
186+
self.tmp_settings_toml,
187+
settings_payload,
188+
create_if_missing=True,
189+
on_error="raise",
190+
)
191+
log.info(f"Settings TOML test data written successfully to {self.tmp_settings_toml}.")
192+
193+
log.info(f"Writing content TOML test data to {self.tmp_content_toml}.")
194+
write_toml(
195+
self.tmp_content_toml,
196+
content_payload,
197+
create_if_missing=True,
198+
on_error="raise",
199+
)
200+
log.info(f"Content TOML test data written successfully to {self.tmp_content_toml}.")
201+
202+
log.info("Loading merged configuration from both TOML files.")
203+
config = load_config_files(self.tmp_settings_toml, self.tmp_content_toml)
204+
log.info(
205+
"Merged config loaded: pipelines.ai.enabled=%s, pipelines.ai.ai_model=%s",
206+
config.pipelines.ai.enabled,
207+
config.pipelines.ai.ai_model,
208+
)
209+
210+
log.info(f"Writing JSON test data to {self.tmp_json}.")
211+
write_json(self.tmp_json, users_payload, create_if_missing=True, on_error="raise")
212+
log.info(f"JSON test data written successfully to {self.tmp_json}.")
213+
214+
log.info(f"Reading JSON test data from {self.tmp_json}.")
215+
read_json(self.tmp_json, on_error="raise")
216+
log.info(f"JSON test data read successfully from {self.tmp_json}.")
217+
218+
log.info("Static IO test run finished successfully.")
219+
220+
221+
if __name__ == "__main__":
222+
StaticTestRunner().run()

tests/tmp_tests/static_test.py

Lines changed: 0 additions & 107 deletions
This file was deleted.

0 commit comments

Comments
 (0)