Skip to content

Commit 9e0e11a

Browse files
committed
Adding missing tests for JSON schema validation
1 parent c6a640b commit 9e0e11a

File tree

3 files changed

+109
-2
lines changed

3 files changed

+109
-2
lines changed

config/config/config.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,9 @@ def get(self, key: str, /, default: Any = None, set_if_not_found: bool = False)
6767
# elif not isinstance(config, (int, float, bool)):
6868
# raise KeyError(f"The provided key '{key}' is not a valid endpoint for a configuration value.")
6969
_trace(f"Config value for key '{key}': {config}")
70+
71+
if not isinstance(config, (str, int, float, bool)):
72+
raise KeyError(f"The provided key '{key}' is not a valid endpoint for a configuration value.")
7073
return config
7174

7275
def set(self, key: str, value : Any) -> 'BaseConfig':
@@ -398,7 +401,7 @@ class MemoryConfig(BaseConfig):
398401
This class provides methods to load, save, and manage configuration settings in memory.
399402
Does not persist to a file.
400403
"""
401-
def __init__(self, initial: Dict[str, Any] = None):
404+
def __init__(self, initial: Dict[str, Any]|None = None):
402405
super().__init__()
403406
if initial is not None:
404407
self._config = initial

config/tests/json_tests.py

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,3 +179,90 @@ def test_load_json_list(temp_json_file):
179179
# Act
180180
with pytest.raises(ValueError):
181181
JSONConfig(temp_json_file)
182+
183+
184+
def test_json_schema_validation_success(temp_json_file, monkeypatch):
185+
# Arrange
186+
schema = {
187+
"type": "object",
188+
"properties": {
189+
"foo": {"type": "string"}
190+
},
191+
"required": ["foo"]
192+
}
193+
194+
content = {"$schema": "http://example.com/schema", "foo": "bar"}
195+
with open(temp_json_file, "w", encoding="utf-8") as f:
196+
json.dump(content, f)
197+
198+
class DummyResponse:
199+
def raise_for_status(self):
200+
return None
201+
202+
def json(self):
203+
return schema
204+
205+
monkeypatch.setattr("requests.get", lambda url: DummyResponse())
206+
207+
# Act / Assert - should not raise
208+
JSONConfig(temp_json_file)
209+
210+
211+
def test_json_schema_fetch_failure(temp_json_file, monkeypatch):
212+
# Arrange
213+
content = {"$schema": "http://example.com/schema", "foo": "bar"}
214+
with open(temp_json_file, "w", encoding="utf-8") as f:
215+
json.dump(content, f)
216+
217+
def raise_exc(url):
218+
raise Exception("network error")
219+
220+
monkeypatch.setattr("requests.get", raise_exc)
221+
222+
# Act / Assert
223+
with pytest.raises(ValueError) as exc:
224+
JSONConfig(temp_json_file)
225+
assert "An error occurred during schema validation" in str(exc.value)
226+
227+
228+
def test_json_schema_validation_failure(temp_json_file, monkeypatch):
229+
# Arrange: schema requires foo to be integer but file has string
230+
schema = {
231+
"type": "object",
232+
"properties": {
233+
"foo": {"type": "integer"}
234+
},
235+
"required": ["foo"]
236+
}
237+
238+
content = {"$schema": "http://example.com/schema", "foo": "not-an-int"}
239+
with open(temp_json_file, "w", encoding="utf-8") as f:
240+
json.dump(content, f)
241+
242+
class DummyResponse:
243+
def raise_for_status(self):
244+
return None
245+
246+
def json(self):
247+
return schema
248+
249+
monkeypatch.setattr("requests.get", lambda url: DummyResponse())
250+
251+
# Act / Assert - validation should fail and raise ValueError
252+
with pytest.raises(ValueError) as exc:
253+
JSONConfig(temp_json_file)
254+
assert "Configuration validation against schema failed" in str(exc.value)
255+
256+
257+
def test_require_validation_without_schema(tmp_path):
258+
# Arrange
259+
file_path = tmp_path / "no_schema.json"
260+
with open(file_path, "w", encoding="utf-8") as f:
261+
json.dump({"foo": "bar"}, f)
262+
263+
# Act / Assert
264+
with pytest.raises(ValueError) as exc:
265+
JSONConfig(str(file_path), True)
266+
assert "JSON schema validation is required but no '$schema' key found in configuration" in str(exc.value)
267+
268+

makefile

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,32 @@
11

22
VERSION = $(shell python get_version.py)
33

4+
DEPENDENCIES_NAMES = jsonschema requests tomlkit coverage pytest
5+
46
MODULES = cache colors config http_code version singleton
57

68
TARGETS = $(addprefix dist/,$(addsuffix -$(VERSION).tar.gz,$(MODULES)))
79
TARGETS += $(addprefix dist/,$(addsuffix -$(VERSION)-py3-none-any.whl,$(MODULES)))
810

11+
PYTHON_PATH = $(shell if [ -d env/bin ]; then echo "env/bin/"; elif [ -d env/Scripts ]; then echo "env/Scripts/"; else echo ""; fi)
12+
PYTHON_LIB = $(shell find env/lib -type d -name "site-packages" | head -n 1; if [ -d env/Lib/site-packages ]; then echo "env/Lib/site-packages/"; fi)
13+
PYTHON = $(PYTHON_PATH)python
14+
915
.PHONY: all clean tests
1016

1117
all: $(TARGETS)
1218

19+
20+
# Dependencies handling
21+
22+
DEPENDENCIES_PATHS = $(addprefix $(PYTHON_LIB)/,$(DEPENDENCIES_NAMES))
23+
24+
$(PYTHON_LIB)/%:
25+
$(PYTHON) -m pip install $*
26+
27+
install: $(DEPENDENCIES_PATHS)
28+
29+
1330
dist/%-$(VERSION)-py3-none-any.whl: % %/pyproject.toml
1431
python build_package.py --version $(VERSION) --wheel --outdir dist $<
1532
@rm -rf $</$<.egg-info $</build
@@ -18,7 +35,7 @@ dist/%-$(VERSION).tar.gz: % %/pyproject.toml
1835
python build_package.py --version $(VERSION) --sdist --outdir dist $<
1936
@rm -rf $</$<.egg-info $</build
2037

21-
tests/%: % #with pytest
38+
tests/%: % install
2239
-@coverage run --data-file $<.coverage --branch -m pytest --tb=short --disable-warnings --junitxml=tests_reports/$*/report.xml $<
2340
@coverage html -d tests_reports/$*/coverage --data-file $<.coverage
2441
@coverage xml -o tests_reports/$*/coverage.xml --data-file $<.coverage

0 commit comments

Comments
 (0)