Replace subprocess tests with in-process async servers (#2006)

* Use anyio as testing backend

* Remove asyncio markers

* Update streamable http tests

* Replace all subprocess tests

* Replace anyio task groups with asyncio context managers in tests

- Convert run_server_async from anyio task group pattern to asyncio.create_task with async context manager
- Remove task_group fixture from conftest
- Update all test fixtures to use async with run_server_async pattern
- Remove TaskGroup imports from all test files
- Tests now work with pytest-asyncio instead of pytest-anyio

* Update test_github_provider_integration.py
This commit is contained in:
Jeremiah Lowin 2025-10-19 10:47:54 -04:00 committed by GitHub
commit 3321644ad3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
28 changed files with 411 additions and 358 deletions

View file

@ -352,7 +352,6 @@ class TestOpenAPIComprehensive:
},
}
@pytest.mark.asyncio
async def test_comprehensive_server_initialization(
self, comprehensive_openapi_spec
):
@ -387,7 +386,6 @@ class TestOpenAPIComprehensive:
assert tool_names == expected_operations
@pytest.mark.asyncio
async def test_openapi_31_compatibility(self, openapi_31_spec):
"""Test that OpenAPI 3.1 specs work correctly."""
async with httpx.AsyncClient(base_url="https://api.example.com") as client:
@ -404,7 +402,6 @@ class TestOpenAPIComprehensive:
tool = tools[0]
assert tool.name == "get_item_31"
@pytest.mark.asyncio
async def test_parameter_collision_handling(self, comprehensive_openapi_spec):
"""Test that parameter collisions are handled correctly."""
async with httpx.AsyncClient(base_url="https://api.example.com") as client:
@ -436,7 +433,6 @@ class TestOpenAPIComprehensive:
# Should have other parameters
assert "data" in param_names
@pytest.mark.asyncio
async def test_deep_object_parameters(self, comprehensive_openapi_spec):
"""Test deepObject parameter handling."""
async with httpx.AsyncClient(base_url="https://api.example.com") as client:
@ -462,7 +458,6 @@ class TestOpenAPIComprehensive:
filter_params = [name for name in properties.keys() if "filter" in name]
assert len(filter_params) > 0
@pytest.mark.asyncio
async def test_request_building_and_execution(self, comprehensive_openapi_spec):
"""Test that requests are built and executed correctly."""
# Create a mock client that tracks requests
@ -503,7 +498,6 @@ class TestOpenAPIComprehensive:
assert "123" in str(request.url)
assert "users/123" in str(request.url)
@pytest.mark.asyncio
async def test_complex_request_with_body_and_parameters(
self, comprehensive_openapi_spec
):
@ -554,7 +548,6 @@ class TestOpenAPIComprehensive:
assert body_data["email"] == "new@example.com"
assert body_data["age"] == 25
@pytest.mark.asyncio
async def test_query_parameters(self, comprehensive_openapi_spec):
"""Test query parameter handling."""
mock_client = Mock(spec=httpx.AsyncClient)
@ -593,7 +586,6 @@ class TestOpenAPIComprehensive:
assert "offset=10" in url_str
assert "sort=name" in url_str
@pytest.mark.asyncio
async def test_error_handling(self, comprehensive_openapi_spec):
"""Test error handling for HTTP errors."""
mock_client = Mock(spec=httpx.AsyncClient)
@ -630,7 +622,6 @@ class TestOpenAPIComprehensive:
error_message = str(exc_info.value)
assert "404" in error_message
@pytest.mark.asyncio
async def test_schema_refs_resolution(self, comprehensive_openapi_spec):
"""Test that schema references are resolved correctly."""
async with httpx.AsyncClient(base_url="https://api.example.com") as client:
@ -652,7 +643,6 @@ class TestOpenAPIComprehensive:
assert "email" in properties
# May also have id and age depending on implementation
@pytest.mark.asyncio
async def test_optional_vs_required_parameters(self, comprehensive_openapi_spec):
"""Test handling of optional vs required parameters."""
async with httpx.AsyncClient(base_url="https://api.example.com") as client:
@ -680,7 +670,6 @@ class TestOpenAPIComprehensive:
# Should have some required parameters
assert len(search_schema["properties"]) > 0
@pytest.mark.asyncio
async def test_server_performance_no_latency(self, comprehensive_openapi_spec):
"""Test that server initialization is fast (no code generation latency)."""
import time

View file

@ -174,7 +174,6 @@ class TestDeepObjectStyle:
},
}
@pytest.mark.asyncio
async def test_deepobject_style_parsing_from_spec(self, deepobject_spec):
"""Test that deepObject style parameters are correctly parsed from OpenAPI spec."""
async with httpx.AsyncClient(base_url="https://api.example.com") as client:
@ -208,7 +207,6 @@ class TestDeepObjectStyle:
# Should have some structure, exact format may vary
assert target_param is not None
@pytest.mark.asyncio
async def test_deepobject_explode_true_handling(self, deepobject_spec):
"""Test deepObject with explode=true parameter handling."""
async with httpx.AsyncClient(base_url="https://api.example.com") as client:
@ -234,7 +232,6 @@ class TestDeepObjectStyle:
assert "type" in target_properties
assert target_properties["type"]["enum"] == ["location", "organisation"]
@pytest.mark.asyncio
async def test_deepobject_explode_false_handling(self, deepobject_spec):
"""Test deepObject with explode=false parameter handling."""
async with httpx.AsyncClient(base_url="https://api.example.com") as client:
@ -263,7 +260,6 @@ class TestDeepObjectStyle:
if "type" in compact_param:
assert compact_param["type"] == "object"
@pytest.mark.asyncio
async def test_nested_object_structure_in_request_body(self, deepobject_spec):
"""Test nested object structures in request body are preserved."""
async with httpx.AsyncClient(base_url="https://api.example.com") as client:
@ -308,7 +304,6 @@ class TestDeepObjectStyle:
assert "push" in notif_props
assert "frequency" in notif_props
@pytest.mark.asyncio
async def test_deepobject_tool_functionality(self, deepobject_spec):
"""Test that tools with deepObject parameters maintain basic functionality."""
async with httpx.AsyncClient(base_url="https://api.example.com") as client:

View file

@ -124,7 +124,6 @@ class TestParameterHandling:
},
}
@pytest.mark.asyncio
async def test_query_parameters_in_tools(self, parameter_spec):
"""Test that query parameters are properly included in tool parameters."""
async with httpx.AsyncClient(base_url="https://api.example.com") as client:
@ -173,7 +172,6 @@ class TestParameterHandling:
assert "query" in required
assert "X-API-Key" in required
@pytest.mark.asyncio
async def test_path_parameters_in_tools(self, parameter_spec):
"""Test that path parameters are properly included in tool parameters."""
async with httpx.AsyncClient(base_url="https://api.example.com") as client:
@ -279,7 +277,6 @@ class TestRequestBodyHandling:
},
}
@pytest.mark.asyncio
async def test_request_body_properties_in_tool(self, request_body_spec):
"""Test that request body properties are included in tool parameters."""
async with httpx.AsyncClient(base_url="https://api.example.com") as client:
@ -381,7 +378,6 @@ class TestResponseSchemas:
},
}
@pytest.mark.asyncio
async def test_tool_has_output_schema(self, response_schema_spec):
"""Test that tools have output schemas from response definitions."""
async with httpx.AsyncClient(base_url="https://api.example.com") as client:

View file

@ -118,7 +118,6 @@ class TestParameterCollisions:
},
}
@pytest.mark.asyncio
async def test_path_body_collision_handling(self, collision_spec):
"""Test that path and body parameters with same name are handled correctly."""
async with httpx.AsyncClient(base_url="https://api.example.com") as client:
@ -159,7 +158,6 @@ class TestParameterCollisions:
id_required = any("id" in req for req in required)
assert id_required
@pytest.mark.asyncio
async def test_query_header_collision_handling(self, collision_spec):
"""Test that query and header parameters with same name are handled correctly."""
async with httpx.AsyncClient(base_url="https://api.example.com") as client:
@ -190,7 +188,6 @@ class TestParameterCollisions:
query_required = any("query" in req for req in required)
assert query_required
@pytest.mark.asyncio
async def test_collision_resolution_maintains_functionality(self, collision_spec):
"""Test that collision resolution doesn't break basic tool functionality."""
async with httpx.AsyncClient(base_url="https://api.example.com") as client:

View file

@ -112,7 +112,6 @@ class TestFastMCPOpenAPIBasicFunctionality:
# Should use default name
assert server.name == "OpenAPI FastMCP"
@pytest.mark.asyncio
async def test_server_creates_tools_from_spec(self, simple_openapi_spec):
"""Test that server creates tools from OpenAPI spec."""
async with httpx.AsyncClient(base_url="https://api.example.com") as client:
@ -131,7 +130,6 @@ class TestFastMCPOpenAPIBasicFunctionality:
assert "get_user" in tool_names
assert "create_user" in tool_names
@pytest.mark.asyncio
async def test_server_tool_execution_fallback_to_http(self, simple_openapi_spec):
"""Test tool execution falls back to HTTP when callables aren't available."""
# Use a mock client that will be used for HTTP fallback
@ -203,7 +201,6 @@ class TestFastMCPOpenAPIBasicFunctionality:
assert hasattr(server, "_director")
assert hasattr(server, "_spec")
@pytest.mark.asyncio
async def test_clean_schema_output_no_unused_defs(self):
"""Test that unused schema definitions are removed from tool schemas."""
# Create a spec with unused HTTPValidationError-like definitions