Skip to content

Commit ca9dfa1

Browse files
committed
test: added tests cases for decorator
1 parent 0ea227c commit ca9dfa1

File tree

3 files changed

+104
-11
lines changed

3 files changed

+104
-11
lines changed

tests/resources/test_answer.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -76,12 +76,12 @@ def test_generate_answer_with_prompts(client, mocker, mock_response):
7676
@pytest.mark.parametrize(
7777
"ns, q, tk, model, temp, history, msg",
7878
[
79-
("", "q", 5, "m", 0.5, [], "'namespace' must be a non-empty string"),
80-
(None, "q", 5, "m", 0.5, [], "'namespace' must be a non-empty string"),
81-
("ns", "", 5, "m", 0.5, [], "'query' must be a non-empty string"),
79+
("", "q", 5, "m", 0.5, [], "Argument 'namespace' cannot be empty."),
80+
(None, "q", 5, "m", 0.5, [], "Argument 'namespace' cannot be None."),
81+
("ns", "", 5, "m", 0.5, [], "Argument 'query' cannot be empty."),
8282
("ns", "q", 0, "m", 0.5, [], "'top_k' must be a positive integer"),
8383
("ns", "q", -1, "m", 0.5, [], "'top_k' must be a positive integer"),
84-
("ns", "q", 5, "", 0.5, [], "'ai_model' must be a non-empty string"),
84+
("ns", "q", 5, "", 0.5, [], "Argument 'ai_model' cannot be empty."),
8585
(
8686
"ns",
8787
"q",

tests/resources/test_namespaces.py

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,8 @@ def test_create_namespace_conflict(client, mocker, mock_response):
8484
@pytest.mark.parametrize(
8585
"name, ns_type, dim, expected_error_msg",
8686
[
87-
("", "text", None, "'namespace_name' must be a non-empty string"),
88-
(None, "text", None, "'namespace_name' must be a non-empty string"),
87+
("", "text", None, "Argument 'namespace_name' cannot be empty."),
88+
(None, "text", None, "Argument 'namespace_name' cannot be None."),
8989
("test", "invalid_type", None, "Namespace type must be 'text' or 'vector'"),
9090
(
9191
"test",
@@ -250,11 +250,20 @@ def test_delete_namespace_not_found(client, mocker, mock_response):
250250
client._mock_httpx_instance.request.assert_called_once()
251251

252252

253-
@pytest.mark.parametrize("invalid_name", ["", None, 123])
254-
def test_delete_namespace_invalid_name_client_side(client, invalid_name):
253+
@pytest.mark.parametrize(
254+
"invalid_name, expected_error",
255+
[
256+
("", "Argument 'namespace_name' cannot be empty."),
257+
(None, "Argument 'namespace_name' cannot be None."),
258+
(123, "Argument 'namespace_name' must be of type <class 'str'>."),
259+
],
260+
)
261+
def test_delete_namespace_invalid_name_client_side(
262+
client, invalid_name, expected_error
263+
):
255264
"""Test client-side validation for delete_namespace name."""
256-
with pytest.raises(
257-
InvalidInputError, match="'namespace_name' must be a non-empty string"
258-
):
265+
import re
266+
267+
with pytest.raises(InvalidInputError, match=re.escape(expected_error)):
259268
client.namespaces.delete(invalid_name)
260269
client._mock_httpx_instance.request.assert_not_called()

tests/utils/test_decorators.py

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
import pytest
2+
3+
from moorcheh_sdk.exceptions import InvalidInputError
4+
from moorcheh_sdk.utils.decorators import required_args
5+
6+
7+
class TestClass:
8+
@required_args(["a", "b"], types={"a": int, "b": str})
9+
def method(self, a, b, c=None):
10+
return a, b, c
11+
12+
13+
def test_required_args_success():
14+
"""Test that the decorator allows valid arguments."""
15+
obj = TestClass()
16+
assert obj.method(1, "test") == (1, "test", None)
17+
assert obj.method(a=1, b="test", c="optional") == (1, "test", "optional")
18+
19+
20+
def test_required_args_missing_arg():
21+
"""Test that missing required arguments raise TypeError (caught and re-raised as InvalidInputError)."""
22+
obj = TestClass()
23+
# If an argument is missing from the call, python's bind will raise TypeError
24+
with pytest.raises(InvalidInputError):
25+
obj.method(a=1)
26+
27+
28+
def test_required_args_none_value():
29+
"""Test that None values for required arguments raise InvalidInputError."""
30+
obj = TestClass()
31+
with pytest.raises(InvalidInputError, match="Argument 'a' cannot be None."):
32+
obj.method(a=None, b="test")
33+
34+
with pytest.raises(InvalidInputError, match="Argument 'b' cannot be None."):
35+
obj.method(a=1, b=None)
36+
37+
38+
def test_required_args_empty_value():
39+
"""Test that empty values for string/list arguments raise InvalidInputError."""
40+
obj = TestClass()
41+
with pytest.raises(InvalidInputError, match="Argument 'b' cannot be empty."):
42+
obj.method(a=1, b="")
43+
44+
45+
def test_required_args_wrong_type():
46+
"""Test that arguments with wrong types raise InvalidInputError."""
47+
obj = TestClass()
48+
with pytest.raises(
49+
InvalidInputError, match="Argument 'a' must be of type <class 'int'>."
50+
):
51+
obj.method(a="not an int", b="test")
52+
53+
with pytest.raises(
54+
InvalidInputError, match="Argument 'b' must be of type <class 'str'>."
55+
):
56+
obj.method(a=1, b=123)
57+
58+
59+
def test_required_args_allow_zero_false():
60+
"""Test that 0 and False are not considered empty."""
61+
62+
@required_args(["num", "flag"], types={"num": int, "flag": bool})
63+
def func(num, flag):
64+
return num, flag
65+
66+
assert func(0, False) == (0, False)
67+
68+
69+
def test_required_args_list_validation():
70+
"""Test validation for list types."""
71+
72+
@required_args(["items"], types={"items": list})
73+
def func(items):
74+
return items
75+
76+
assert func([1, 2]) == [1, 2]
77+
78+
with pytest.raises(InvalidInputError, match="Argument 'items' cannot be empty."):
79+
func([])
80+
81+
with pytest.raises(
82+
InvalidInputError, match="Argument 'items' must be of type <class 'list'>."
83+
):
84+
func("not a list")

0 commit comments

Comments
 (0)