Skip to content

Commit cd1d6a2

Browse files
committed
chore: Reorder tests in matching classes.
This will improve maintainability.
1 parent 1fab524 commit cd1d6a2

File tree

1 file changed

+98
-176
lines changed

1 file changed

+98
-176
lines changed

packages/toolbox-core/tests/test_client.py

Lines changed: 98 additions & 176 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,60 @@ async def test_load_toolset_success(aioresponses, test_tool_str, test_tool_int_b
131131
assert {t.__name__ for t in tools} == manifest.tools.keys()
132132

133133

134+
@pytest.mark.asyncio
135+
async def test_invoke_tool_server_error(aioresponses, test_tool_str):
136+
"""Tests that invoking a tool raises an Exception when the server returns an
137+
error status."""
138+
TOOL_NAME = "server_error_tool"
139+
ERROR_MESSAGE = "Simulated Server Error"
140+
manifest = ManifestSchema(serverVersion="0.0.0", tools={TOOL_NAME: test_tool_str})
141+
142+
aioresponses.get(
143+
f"{TEST_BASE_URL}/api/tool/{TOOL_NAME}",
144+
payload=manifest.model_dump(),
145+
status=200,
146+
)
147+
aioresponses.post(
148+
f"{TEST_BASE_URL}/api/tool/{TOOL_NAME}/invoke",
149+
payload={"error": ERROR_MESSAGE},
150+
status=500,
151+
)
152+
153+
async with ToolboxClient(TEST_BASE_URL) as client:
154+
loaded_tool = await client.load_tool(TOOL_NAME)
155+
156+
with pytest.raises(Exception, match=ERROR_MESSAGE):
157+
await loaded_tool(param1="some input")
158+
159+
160+
@pytest.mark.asyncio
161+
async def test_load_tool_not_found_in_manifest(aioresponses, test_tool_str):
162+
"""
163+
Tests that load_tool raises an Exception when the requested tool name
164+
is not found in the manifest returned by the server, using existing fixtures.
165+
"""
166+
ACTUAL_TOOL_IN_MANIFEST = "actual_tool_abc"
167+
REQUESTED_TOOL_NAME = "non_existent_tool_xyz"
168+
169+
manifest = ManifestSchema(
170+
serverVersion="0.0.0", tools={ACTUAL_TOOL_IN_MANIFEST: test_tool_str}
171+
)
172+
173+
aioresponses.get(
174+
f"{TEST_BASE_URL}/api/tool/{REQUESTED_TOOL_NAME}",
175+
payload=manifest.model_dump(),
176+
status=200,
177+
)
178+
179+
async with ToolboxClient(TEST_BASE_URL) as client:
180+
with pytest.raises(Exception, match=f"Tool '{REQUESTED_TOOL_NAME}' not found!"):
181+
await client.load_tool(REQUESTED_TOOL_NAME)
182+
183+
aioresponses.assert_called_once_with(
184+
f"{TEST_BASE_URL}/api/tool/{REQUESTED_TOOL_NAME}", method="GET"
185+
)
186+
187+
134188
class TestAuth:
135189

136190
@pytest.fixture
@@ -183,7 +237,7 @@ def token_handler():
183237
tool = await client.load_tool(
184238
tool_name, auth_token_getters={"my-auth-service": token_handler}
185239
)
186-
res = await tool(5)
240+
await tool(5)
187241

188242
@pytest.mark.asyncio
189243
async def test_auth_with_add_token_success(
@@ -196,20 +250,35 @@ def token_handler():
196250

197251
tool = await client.load_tool(tool_name)
198252
tool = tool.add_auth_token_getters({"my-auth-service": token_handler})
199-
res = await tool(5)
253+
await tool(5)
200254

201255
@pytest.mark.asyncio
202256
async def test_auth_with_load_tool_fail_no_token(
203257
self, tool_name, expected_header, client
204258
):
205259
"""Tests 'load_tool' with auth token is specified."""
206260

207-
def token_handler():
208-
return expected_header
209-
210261
tool = await client.load_tool(tool_name)
211262
with pytest.raises(Exception):
212-
res = await tool(5)
263+
await tool(5)
264+
265+
@pytest.mark.asyncio
266+
async def test_add_auth_token_getters_duplicate_fail(self, tool_name, client):
267+
"""
268+
Tests that adding a duplicate auth token getter raises ValueError.
269+
"""
270+
AUTH_SERVICE = "my-auth-service"
271+
272+
tool = await client.load_tool(tool_name)
273+
274+
authed_tool = tool.add_auth_token_getters({AUTH_SERVICE: {}})
275+
assert AUTH_SERVICE in authed_tool._ToolboxTool__auth_service_token_getters
276+
277+
with pytest.raises(
278+
ValueError,
279+
match=f"Authentication source\\(s\\) `{AUTH_SERVICE}` already registered in tool `{tool_name}`.",
280+
):
281+
authed_tool.add_auth_token_getters({AUTH_SERVICE: {}})
213282

214283

215284
class TestBoundParameter:
@@ -319,62 +388,15 @@ async def test_bind_param_fail(self, tool_name, client):
319388
with pytest.raises(Exception):
320389
tool = tool.bind_parameters({"argC": lambda: 5})
321390

391+
@pytest.mark.asyncio
392+
async def test_bind_param_static_value_success(self, tool_name, client):
393+
"""
394+
Tests bind_parameters method with a static value.
395+
"""
322396

323-
@pytest.mark.asyncio
324-
async def test_invoke_tool_server_error(aioresponses, test_tool_str):
325-
"""Tests that invoking a tool raises an Exception when the server returns an
326-
error status."""
327-
TOOL_NAME = "server_error_tool"
328-
ERROR_MESSAGE = "Simulated Server Error"
329-
manifest = ManifestSchema(serverVersion="0.0.0", tools={TOOL_NAME: test_tool_str})
330-
331-
aioresponses.get(
332-
f"{TEST_BASE_URL}/api/tool/{TOOL_NAME}",
333-
payload=manifest.model_dump(),
334-
status=200,
335-
)
336-
aioresponses.post(
337-
f"{TEST_BASE_URL}/api/tool/{TOOL_NAME}/invoke",
338-
payload={"error": ERROR_MESSAGE},
339-
status=500,
340-
)
341-
342-
async with ToolboxClient(TEST_BASE_URL) as client:
343-
loaded_tool = await client.load_tool(TOOL_NAME)
344-
345-
with pytest.raises(Exception, match=ERROR_MESSAGE):
346-
await loaded_tool(param1="some input")
347-
348-
349-
@pytest.mark.asyncio
350-
async def test_bind_param_static_value_success(aioresponses, test_tool_int_bool):
351-
"""
352-
Tests bind_parameters method with a static value.
353-
"""
354-
TOOL_NAME = "async_bind_tool"
355-
manifest = ManifestSchema(
356-
serverVersion="0.0.0", tools={TOOL_NAME: test_tool_int_bool}
357-
)
358-
359-
aioresponses.get(
360-
f"{TEST_BASE_URL}/api/tool/{TOOL_NAME}",
361-
payload=manifest.model_dump(),
362-
status=200,
363-
)
364-
365-
def reflect_parameters(url, **kwargs):
366-
received_params = kwargs.get("json", {})
367-
return CallbackResult(status=200, payload={"result": received_params})
368-
369-
aioresponses.post(
370-
f"{TEST_BASE_URL}/api/tool/{TOOL_NAME}/invoke",
371-
callback=reflect_parameters,
372-
)
373-
374-
bound_value = "Test value"
397+
bound_value = "Test value"
375398

376-
async with ToolboxClient(TEST_BASE_URL) as client:
377-
tool = await client.load_tool(TOOL_NAME)
399+
tool = await client.load_tool(tool_name)
378400
bound_tool = tool.bind_parameters({"argB": bound_value})
379401

380402
assert bound_tool is not tool
@@ -386,37 +408,16 @@ def reflect_parameters(url, **kwargs):
386408

387409
assert res_payload == {"argA": passed_value_a, "argB": bound_value}
388410

411+
@pytest.mark.asyncio
412+
async def test_bind_param_sync_callable_value_success(self, tool_name, client):
413+
"""
414+
Tests bind_parameters method with a sync callable value.
415+
"""
389416

390-
@pytest.mark.asyncio
391-
async def test_bind_param_sync_callable_value_success(aioresponses, test_tool_int_bool):
392-
"""
393-
Tests bind_parameters method with a sync callable value.
394-
"""
395-
TOOL_NAME = "async_bind_tool"
396-
manifest = ManifestSchema(
397-
serverVersion="0.0.0", tools={TOOL_NAME: test_tool_int_bool}
398-
)
399-
400-
aioresponses.get(
401-
f"{TEST_BASE_URL}/api/tool/{TOOL_NAME}",
402-
payload=manifest.model_dump(),
403-
status=200,
404-
)
405-
406-
def reflect_parameters(url, **kwargs):
407-
received_params = kwargs.get("json", {})
408-
return CallbackResult(status=200, payload={"result": received_params})
409-
410-
aioresponses.post(
411-
f"{TEST_BASE_URL}/api/tool/{TOOL_NAME}/invoke",
412-
callback=reflect_parameters,
413-
)
414-
415-
bound_value_result = True
416-
bound_sync_callable = Mock(return_value=bound_value_result)
417+
bound_value_result = True
418+
bound_sync_callable = Mock(return_value=bound_value_result)
417419

418-
async with ToolboxClient(TEST_BASE_URL) as client:
419-
tool = await client.load_tool(TOOL_NAME)
420+
tool = await client.load_tool(tool_name)
420421
bound_tool = tool.bind_parameters({"argB": bound_sync_callable})
421422

422423
assert bound_tool is not tool
@@ -429,39 +430,16 @@ def reflect_parameters(url, **kwargs):
429430
assert res_payload == {"argA": passed_value_a, "argB": bound_value_result}
430431
bound_sync_callable.assert_called_once()
431432

433+
@pytest.mark.asyncio
434+
async def test_bind_param_async_callable_value_success(self, tool_name, client):
435+
"""
436+
Tests bind_parameters method with an async callable value.
437+
"""
432438

433-
@pytest.mark.asyncio
434-
async def test_bind_param_async_callable_value_success(
435-
aioresponses, test_tool_int_bool
436-
):
437-
"""
438-
Tests bind_parameters method with an async callable value.
439-
"""
440-
TOOL_NAME = "async_bind_tool"
441-
manifest = ManifestSchema(
442-
serverVersion="0.0.0", tools={TOOL_NAME: test_tool_int_bool}
443-
)
444-
445-
aioresponses.get(
446-
f"{TEST_BASE_URL}/api/tool/{TOOL_NAME}",
447-
payload=manifest.model_dump(),
448-
status=200,
449-
)
450-
451-
def reflect_parameters(url, **kwargs):
452-
received_params = kwargs.get("json", {})
453-
return CallbackResult(status=200, payload={"result": received_params})
454-
455-
aioresponses.post(
456-
f"{TEST_BASE_URL}/api/tool/{TOOL_NAME}/invoke",
457-
callback=reflect_parameters,
458-
)
459-
460-
bound_value_result = True
461-
bound_async_callable = AsyncMock(return_value=bound_value_result)
439+
bound_value_result = True
440+
bound_async_callable = AsyncMock(return_value=bound_value_result)
462441

463-
async with ToolboxClient(TEST_BASE_URL) as client:
464-
tool = await client.load_tool(TOOL_NAME)
442+
tool = await client.load_tool(tool_name)
465443
bound_tool = tool.bind_parameters({"argB": bound_async_callable})
466444

467445
assert bound_tool is not tool
@@ -473,59 +451,3 @@ def reflect_parameters(url, **kwargs):
473451

474452
assert res_payload == {"argA": passed_value_a, "argB": bound_value_result}
475453
bound_async_callable.assert_awaited_once()
476-
477-
478-
@pytest.mark.asyncio
479-
async def test_add_auth_token_getters_duplicate_fail(aioresponses, test_tool_auth):
480-
"""
481-
Tests that adding a duplicate auth token getter raises ValueError.
482-
"""
483-
TOOL_NAME = "duplicate_auth_tool"
484-
AUTH_SERVICE = "my-auth-service"
485-
manifest = ManifestSchema(serverVersion="0.0.0", tools={TOOL_NAME: test_tool_auth})
486-
487-
aioresponses.get(
488-
f"{TEST_BASE_URL}/api/tool/{TOOL_NAME}",
489-
payload=manifest.model_dump(),
490-
status=200,
491-
)
492-
493-
async with ToolboxClient(TEST_BASE_URL) as client:
494-
tool = await client.load_tool(TOOL_NAME)
495-
496-
authed_tool = tool.add_auth_token_getters({AUTH_SERVICE: {}})
497-
assert AUTH_SERVICE in authed_tool._ToolboxTool__auth_service_token_getters
498-
499-
with pytest.raises(
500-
ValueError,
501-
match=f"Authentication source\\(s\\) `{AUTH_SERVICE}` already registered in tool `{TOOL_NAME}`.",
502-
):
503-
authed_tool.add_auth_token_getters({AUTH_SERVICE: {}})
504-
505-
506-
@pytest.mark.asyncio
507-
async def test_load_tool_not_found_in_manifest(aioresponses, test_tool_str):
508-
"""
509-
Tests that load_tool raises an Exception when the requested tool name
510-
is not found in the manifest returned by the server, using existing fixtures.
511-
"""
512-
ACTUAL_TOOL_IN_MANIFEST = "actual_tool_abc"
513-
REQUESTED_TOOL_NAME = "non_existent_tool_xyz"
514-
515-
manifest = ManifestSchema(
516-
serverVersion="0.0.0", tools={ACTUAL_TOOL_IN_MANIFEST: test_tool_str}
517-
)
518-
519-
aioresponses.get(
520-
f"{TEST_BASE_URL}/api/tool/{REQUESTED_TOOL_NAME}",
521-
payload=manifest.model_dump(),
522-
status=200,
523-
)
524-
525-
async with ToolboxClient(TEST_BASE_URL) as client:
526-
with pytest.raises(Exception, match=f"Tool '{REQUESTED_TOOL_NAME}' not found!"):
527-
await client.load_tool(REQUESTED_TOOL_NAME)
528-
529-
aioresponses.assert_called_once_with(
530-
f"{TEST_BASE_URL}/api/tool/{REQUESTED_TOOL_NAME}", method="GET"
531-
)

0 commit comments

Comments
 (0)