Skip to content

Commit

Permalink
feat(config-registrar): add comprehensive tests for ConfigKey and Con…
Browse files Browse the repository at this point in the history
…figTree

Implement new tests to ensure proper functionality and edge case handling
for ConfigKey and ConfigTree classes. This includes testing initialization,value setting, type conversion, option handling, and merge capabilities.
Additionally, refactor some code in config_registrar.py for better clarity
and fix a bug where None was an invalid value for ConfigKey.
  • Loading branch information
northgreen committed Jul 7, 2024
1 parent 013a93a commit 9d51a2d
Show file tree
Hide file tree
Showing 2 changed files with 197 additions and 17 deletions.
34 changes: 17 additions & 17 deletions ictye-live-dm/src/ictye_live_dm/depends/config_registrar.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ def __init__(self, default: str | bool | int | float = None,
optional: bool = False,
option: list[str | bool | int | float] = None,
value: str | bool | int | float = None):
if value is None and default is None:
raise ValueError("None ConfigKey is invalid")
# self.__value = default if value is None else value
self.__default = __get_type_default__(type(value)) if default is None else default
self.__optional = optional
self.__option = option if option else [True, False] if isinstance(default, bool) else None
Expand Down Expand Up @@ -129,7 +132,7 @@ def merge(self, other):
@param other: 另一個ConfigKey
@return: 合併後的ConfigKey
"""
if self.__default is None:
if self.__default is __get_type_default__(type(other.get())):
self.__default = other.get_default()

self.set(other.get())
Expand All @@ -140,6 +143,9 @@ def merge(self, other):
if other.is_optional():
self.__optional = True

def __eq__(self, other: "ConfigKey"):
return self.get() == other.get()


class ConfigTree:
"""
Expand Down Expand Up @@ -286,7 +292,7 @@ def __iter__(self):
if self.__is_list:
return iter(self.__list_content)
else:
return iter(self.__content)
return iter(self.__content.items())

def __str__(self):
return str(self.__value)
Expand Down Expand Up @@ -353,7 +359,7 @@ def to_dict(self) -> dict:
ret = {}
if self.is_list():
raise TypeError("Cannot convert list to dict")
for k, v in self:
for k, v in self.items():
if isinstance(v, ConfigTree):
if v.is_list():
ret[k] = v.to_list()
Expand All @@ -371,10 +377,9 @@ def merge(self, other: "ConfigTree") -> "ConfigTree":
@param other: 另一個配置樹
@return: 合併後的配置樹
"""
# TODO: 未完成的部分
if self.is_list() and other.is_list(): # 兩個都是列表
for i in other.values():
self.__list_content.append(i)
self.__list_content.append(i) # TODO:此處邏輯仍然有問題
elif not self.is_list() and not other.is_list(): # 兩個都是字典
for k, v in other.items():
if k in self.__content:
Expand Down Expand Up @@ -439,10 +444,13 @@ def dump(self, value):
self.config = ConfigTree(is_list=True, build_list=value)

def dump_default(self, value):
# TODO:要在這裏合并所有配置
"""
將傳入的作爲默認配置并且合并
@param value:
@return:
"""
if isinstance(value, dict):
self.config = self.config.merge(ConfigTree(build_dict=value))
pass
elif isinstance(value, list):
self.config = self.config.merge(ConfigTree(is_list=True, build_list=value))

Expand Down Expand Up @@ -537,13 +545,5 @@ def __len__(self):


if __name__ == "__main__":
# TODO: 調試代碼
import ipdb

config = ConfigRegistrar()
config.register("test", "test", "test", optional=True, option=["test", "test2"])

key1 = ConfigKey("test", optional=True, option=["test", "test2"])
key2 = ConfigKey("test2", optional=True, option=["test", "test2"], value="test2")
print(repr(key1.merge(key2)))
ipdb.set_trace()
config = ConfigTree(build_dict={'key1': ConfigKey('value1'), 'key2': ConfigKey('value2')})
result_dict = config.to_dict()
180 changes: 180 additions & 0 deletions ictye-live-dm/tests/Config_element_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
import pytest
from ictye_live_dm.depends.config_registrar import ConfigKey,ConfigTree


def test_init_default_none():
with pytest.raises(ValueError):
ConfigKey()


def test_init_with_default_value():
key = ConfigKey(default=5)
assert key.get_default() == 5
assert not key.is_optional()


def test_init_with_optional_true():
key = ConfigKey(optional=True, value="test v1")
assert key.is_optional()
assert key.get_default() == ""
assert key.get() == "test v1"


def test_init_with_options():
key = ConfigKey(default=True, option=[True, False])
assert key.has_option()
assert True in key.get_options()
assert False in key.get_options()


def test_set_value():
key = ConfigKey(value=5)
key.set(10)
assert key.is_set()
assert key.get() != 5
assert key.get() == 10
assert key.get_type() is int


def test_set_value_with_type_conversion():
key = ConfigKey(default=10)
key.set('20')
assert key.get() == 20
assert key.get_type() is int


def test_set_value_out_of_options():
key = ConfigKey(default=True, option=[True, False])
with pytest.raises(ValueError):
key.set('other')


def test_merge_with_non_empty_default():
key1 = ConfigKey(default=10)
key2 = ConfigKey(value=20)
key2.merge(key1)
assert key2.get_default() == 10


def test_merge_with_options():
key1 = ConfigKey(option=[1, 2], value=1)
key2 = ConfigKey(option=[3, 4], value=2)
key1.merge(key2)
with pytest.raises(ValueError):
key1.merge(key2)
assert 3 in key1.get_options()
assert 4 in key1.get_options()


def test_merge_with_optional():
key1 = ConfigKey(optional=False, value=True)
key2 = ConfigKey(optional=True, value=True)
key1.merge(key2)
assert key1.is_optional()


def test_eq():
key1 = ConfigKey(default=5)
key2 = ConfigKey(default=5)
assert key1 == key2


def test_repr():
key = ConfigKey(default=5, optional=True, option=[1, 2], value=10)
expected_repr = "ConfigKey(dfault=5, is optional=True, options=[1, 2], value=10)"
assert repr(key) == expected_repr


# Additional tests for __int__, __float__, __bool__, and __str__
def test_int_conversion():
key = ConfigKey(default=10)
assert int(key) == 10


def test_float_conversion():
key = ConfigKey(default=10.5)
assert float(key) == 10.5


def test_bool_conversion():
key_true = ConfigKey(default=True)
key_false = ConfigKey(default=False)
assert bool(key_true)
assert not bool(key_false)


def test_str_conversion():
key = ConfigKey(default="test")
assert str(key) == "test"


class TestConfigTree:

def test_init_dict(self):
# 测试以字典形式初始化
config = ConfigTree(build_dict={'key1': 'value1', 'key2': {'subkey': 'subvalue'}})
assert 'key1' in config._ConfigTree__content
assert 'key2' in config._ConfigTree__content
assert isinstance(config._ConfigTree__content['key2'], ConfigTree)

def test_init_list(self):
# 测试以列表形式初始化
config = ConfigTree(is_list=True, build_list=[ConfigKey('value1'), {'subkey': 'subvalue'}])
assert isinstance(config._ConfigTree__list_content[0], ConfigKey)
assert isinstance(config._ConfigTree__list_content[1], ConfigTree)

def test_get(self):
# 测试获取值
config = ConfigTree(build_dict={'key': ConfigKey('value')})
assert config.get('key').get() == 'value'

def test_set(self):
# 测试设置值
config = ConfigTree()
config.set('key', ConfigKey('value'))
assert config.get('key').get() == 'value'

def test_iter(self):
# 测试迭代
config = ConfigTree(is_list=True, build_list=[ConfigKey('value1'), ConfigKey('value2')])
values = [value.get() for value in config]
assert values == ['value1', 'value2']

def test_to_dict(self):
# 测试转换为字典
config = ConfigTree(build_dict={'key1': ConfigKey('value1'), 'key2': ConfigKey('value2')})
result_dict = config.to_dict()
assert result_dict == {'key1': 'value1', 'key2': 'value2'}

def test_to_list(self):
# 测试转换为列表
config = ConfigTree(is_list=True, build_list=[ConfigKey('value1'), ConfigKey('value2')])
result_list = config.to_list()
assert result_list == ['value1', 'value2']

def test_merge_dict_with_dict(self):
# 测试合并两个字典
config1 = ConfigTree(build_dict={'key1': ConfigKey('value1')})
config2 = ConfigTree(build_dict={'key2': ConfigKey('value2')})
config1.merge(config2)
assert 'key1' in config1._ConfigTree__content
assert 'key2' in config1._ConfigTree__content

def test_merge_list_with_list(self):
# 测试合并两个列表
config1 = ConfigTree(is_list=True, build_list=[ConfigKey('value1')])
config2 = ConfigTree(is_list=True, build_list=[ConfigKey('value2')])
config1.merge(config2)
assert len(config1._ConfigTree__list_content) == 2

def test_merge_incompatible_types(self):
# 测试合并不同类型引发异常
config1 = ConfigTree(build_dict={'key1': ConfigKey('value1')})
config2 = ConfigTree(is_list=True, build_list=[ConfigKey('value2')])
with pytest.raises(TypeError):
config1.merge(config2)


# 使用pytest运行测试
if __name__ == "__main__":
pytest.main()

0 comments on commit 9d51a2d

Please sign in to comment.