-
-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
updated test_tags.py to align with new tags.py
- Loading branch information
Sankalp Gilda
committed
Oct 7, 2024
1 parent
2d4af60
commit 1c8e284
Showing
1 changed file
with
207 additions
and
32 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,46 +1,221 @@ | ||
"""Tests for tag register an tag functionality.""" | ||
""" | ||
Tests for the tag registry and tag validation functionality. | ||
from tsbootstrap.registry._tags import OBJECT_TAG_REGISTER | ||
This module contains tests to ensure that the `OBJECT_TAG_REGISTER` is correctly | ||
configured and that each tag adheres to the specified structure and type constraints. | ||
""" | ||
|
||
from tsbootstrap.registry._tags import OBJECT_TAG_REGISTER, Tag | ||
|
||
|
||
def test_tag_register_type(): | ||
"""Test the specification of the tag register. See _tags for specs.""" | ||
""" | ||
Test the specification of the tag register. | ||
Ensures that `OBJECT_TAG_REGISTER` is a list of `Tag` instances with the correct attributes and types. | ||
Raises | ||
------ | ||
TypeError | ||
If `OBJECT_TAG_REGISTER` is not a list or contains non-`Tag` instances. | ||
ValueError | ||
If any `Tag` instance does not conform to the expected structure or type constraints. | ||
""" | ||
# Verify that OBJECT_TAG_REGISTER is a list | ||
if not isinstance(OBJECT_TAG_REGISTER, list): | ||
raise TypeError("OBJECT_TAG_REGISTER is not a list.") | ||
if not all(isinstance(tag, tuple) for tag in OBJECT_TAG_REGISTER): | ||
raise TypeError("Not all elements in OBJECT_TAG_REGISTER are tuples.") | ||
raise TypeError("`OBJECT_TAG_REGISTER` is not a list.") | ||
|
||
# Verify that all elements in OBJECT_TAG_REGISTER are instances of Tag | ||
if not all(isinstance(tag, Tag) for tag in OBJECT_TAG_REGISTER): | ||
raise TypeError( | ||
"Not all elements in `OBJECT_TAG_REGISTER` are `Tag` instances." | ||
) | ||
|
||
# Iterate through each Tag instance to validate its attributes | ||
for tag in OBJECT_TAG_REGISTER: | ||
if len(tag) != 4: | ||
raise ValueError("Tag does not have 4 elements.") | ||
if not isinstance(tag[0], str): | ||
raise TypeError("Tag name is not a string.") | ||
if not isinstance(tag[1], (str, list)): | ||
raise TypeError("Tag type is not a string or list.") | ||
if isinstance(tag[1], list) and not all( | ||
isinstance(x, str) for x in tag[1] | ||
): | ||
raise TypeError("Not all elements in tag type list are strings.") | ||
if not isinstance(tag[2], (str, tuple)): | ||
raise TypeError("Tag description is not a string or tuple.") | ||
if isinstance(tag[2], tuple): | ||
if not len(tag[2]) == 2: | ||
# Validate the 'name' attribute | ||
if not isinstance(tag.name, str): | ||
raise TypeError(f"Tag name '{tag.name}' is not a string.") | ||
|
||
# Validate the 'scitype' attribute | ||
if not isinstance(tag.scitype, str): | ||
raise TypeError(f"Tag scitype '{tag.scitype}' is not a string.") | ||
|
||
# Validate the 'value_type' attribute | ||
if not isinstance(tag.value_type, (str, tuple)): | ||
raise TypeError( | ||
f"Tag value_type '{tag.value_type}' is not a string or tuple." | ||
) | ||
|
||
if isinstance(tag.value_type, tuple): | ||
if len(tag.value_type) != 2: | ||
raise ValueError( | ||
"Tag description tuple does not have 2 elements." | ||
"Tuple `value_type` must have exactly two elements." | ||
) | ||
if not isinstance(tag[2][0], str): | ||
raise TypeError( | ||
"Tag description tuple first element is not a string." | ||
|
||
base_type, subtype = tag.value_type | ||
|
||
# Validate the base type | ||
if base_type not in {"str", "list"}: | ||
raise ValueError( | ||
f"First element of `value_type` tuple must be 'str' or 'list', got '{base_type}'." | ||
) | ||
if not isinstance(tag[2][1], (list, str)): | ||
raise TypeError( | ||
"Tag description tuple second element is not a list or string." | ||
|
||
# Validate the subtype based on the base type | ||
if base_type == "str": | ||
if not isinstance(subtype, list) or not all( | ||
isinstance(item, str) for item in subtype | ||
): | ||
raise TypeError( | ||
"Second element of `value_type` tuple must be a list of strings when base is 'str'." | ||
) | ||
elif base_type == "list" and not ( | ||
( | ||
isinstance(subtype, list) | ||
and all(isinstance(item, str) for item in subtype) | ||
) | ||
if isinstance(tag[2][1], list) and not all( | ||
isinstance(x, str) for x in tag[2][1] | ||
or isinstance(subtype, str) | ||
): | ||
raise TypeError( | ||
"Not all elements in tag description list are strings." | ||
"Second element of `value_type` tuple must be a list of strings or 'str' when base is 'list'." | ||
) | ||
|
||
# Validate the 'description' attribute | ||
if not isinstance(tag.description, str): | ||
raise TypeError( | ||
f"Tag description '{tag.description}' is not a string." | ||
) | ||
|
||
|
||
def test_object_tag_table_structure(): | ||
""" | ||
Test the structure of `OBJECT_TAG_TABLE`. | ||
Ensures that `OBJECT_TAG_TABLE` is a list of dictionaries, each containing the expected keys and corresponding types. | ||
Raises | ||
------ | ||
TypeError | ||
If `OBJECT_TAG_TABLE` is not a list or contains elements that are not dictionaries. | ||
KeyError | ||
If any dictionary in `OBJECT_TAG_TABLE` is missing required keys. | ||
TypeError | ||
If any value in the dictionaries does not match the expected type. | ||
""" | ||
from tsbootstrap.registry._tags import OBJECT_TAG_TABLE | ||
|
||
# Define the expected keys and their types | ||
expected_keys = { | ||
"name": str, | ||
"scitype": str, | ||
"value_type": (str, tuple), | ||
"description": str, | ||
} | ||
|
||
# Verify that OBJECT_TAG_TABLE is a list | ||
if not isinstance(OBJECT_TAG_TABLE, list): | ||
raise TypeError("`OBJECT_TAG_TABLE` is not a list.") | ||
|
||
# Iterate through each dictionary in OBJECT_TAG_TABLE to validate its structure | ||
for entry in OBJECT_TAG_TABLE: | ||
# Verify that each entry is a dictionary | ||
if not isinstance(entry, dict): | ||
raise TypeError( | ||
"Each entry in `OBJECT_TAG_TABLE` must be a dictionary." | ||
) | ||
|
||
# Check for the presence of all expected keys | ||
for key, expected_type in expected_keys.items(): | ||
if key not in entry: | ||
raise KeyError( | ||
f"Key '{key}' is missing from an entry in `OBJECT_TAG_TABLE`." | ||
) | ||
|
||
# Validate the type of each value | ||
if not isinstance(entry[key], expected_type): | ||
raise TypeError( | ||
f"Value for key '{key}' in `OBJECT_TAG_TABLE` entry is not of type { | ||
expected_type}." | ||
) | ||
|
||
|
||
def test_object_tag_list(): | ||
""" | ||
Test the contents of `OBJECT_TAG_LIST`. | ||
Ensures that `OBJECT_TAG_LIST` contains all tag names present in `OBJECT_TAG_REGISTER` and that each name is a string. | ||
Raises | ||
------ | ||
TypeError | ||
If `OBJECT_TAG_LIST` is not a list or contains non-string elements. | ||
ValueError | ||
If any tag name in `OBJECT_TAG_register` is missing from `OBJECT_TAG_LIST`. | ||
""" | ||
from tsbootstrap.registry._tags import OBJECT_TAG_LIST | ||
|
||
# Verify that OBJECT_TAG_LIST is a list | ||
if not isinstance(OBJECT_TAG_LIST, list): | ||
raise TypeError("`OBJECT_TAG_LIST` is not a list.") | ||
|
||
# Verify that all elements in OBJECT_TAG_LIST are strings | ||
if not all(isinstance(name, str) for name in OBJECT_TAG_LIST): | ||
raise TypeError("All elements in `OBJECT_TAG_LIST` must be strings.") | ||
|
||
# Extract all tag names from OBJECT_TAG_REGISTER | ||
tag_names = {tag.name for tag in OBJECT_TAG_REGISTER} | ||
|
||
# Verify that OBJECT_TAG_LIST contains all tag names | ||
missing_tags = tag_names - set(OBJECT_TAG_LIST) | ||
if missing_tags: | ||
raise ValueError( | ||
f"The following tags are missing from `OBJECT_TAG_LIST`: {missing_tags}" | ||
) | ||
|
||
|
||
def test_check_tag_is_valid(): | ||
""" | ||
Test the `check_tag_is_valid` function. | ||
Ensures that `check_tag_is_valid` correctly validates tag values based on their expected types. | ||
Raises | ||
------ | ||
AssertionError | ||
If any test case fails. | ||
""" | ||
from tsbootstrap.registry._tags import check_tag_is_valid | ||
|
||
# Define test cases as tuples of (tag_name, tag_value, expected_result) | ||
test_cases = [ | ||
("object_type", "regressor", True), | ||
("object_type", "invalid_type", False), | ||
("capability:multivariate", True, True), | ||
("capability:multivariate", False, True), | ||
("capability:multivariate", "yes", False), | ||
("python_version", "3.8.5", True), | ||
("python_version", 3.8, False), | ||
("python_dependencies", ["numpy", "pandas"], True), | ||
("python_dependencies", "numpy", True), | ||
("python_dependencies", ["numpy", 123], False), | ||
("python_dependencies_alias", {"numpy": "np"}, True), | ||
("python_dependencies_alias", "numpy", False), | ||
("non_existent_tag", "value", False), # Should raise KeyError | ||
] | ||
|
||
for tag_name, tag_value, expected in test_cases: | ||
if tag_name == "non_existent_tag": | ||
try: | ||
check_tag_is_valid(tag_name, tag_value) | ||
raise AssertionError( | ||
f"Expected KeyError for tag '{tag_name}', but no error was raised." | ||
) | ||
except KeyError: | ||
pass # Expected behavior | ||
else: | ||
result = check_tag_is_valid(tag_name, tag_value) | ||
if result != expected: | ||
raise ValueError( | ||
f"check_tag_is_valid({tag_name!r}, {tag_value!r}) returned { | ||
result}, expected {expected}." | ||
) | ||
if not isinstance(tag[3], str): | ||
raise TypeError("Tag source is not a string.") |