feat(testing): build_test_client(platform) async context manager#554
Merged
Conversation
4 tasks
d659bd4 to
ca55abe
Compare
Closes #549 Adds build_test_client(platform) to adcp.testing — a single async context manager that wraps build_asgi_app + LifespanManager + httpx.AsyncClient, eliminating 4 lines of boilerplate from every in-process integration test. Also adds allowed_hosts parameter to build_asgi_app so callers can configure FastMCP's transport-security layer without manual server manipulation. https://claude.ai/code/session_01UZyqrAkoJPCEz5VLerzxFv
ca55abe to
65134a8
Compare
This file contains hidden or 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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #549
Summary
Adds
build_test_client(platform)toadcp.testing— a singleasync withblock that replaces the 4-line boilerplate every in-process integration test previously needed:Also adds
allowed_hosts: Sequence[str] | None = Nonetobuild_asgi_appso callers can configure FastMCP's transport-security layer directly.build_test_clientsets this automatically from thebase_urlhostname.Key implementation notes:
asgi_lifespanis lazy-imported with an actionableImportErrormessage (pip install 'adcp[dev]')build_asgi_appruns insideasyncio.to_thread()becausevalidate_capabilities_response_shapecallsasyncio.run()internally, which fails if a loop is already running in the calling async testfollow_redirects=Truedefault matches all existing ASGI test fixtures (FastMCP can issue a 307 on/mcp→/mcp/)headers=accepted asMapping[str, str] | Noneand forwarded directly tohttpx.AsyncClientNits surfaced in pre-PR review (not fixed — low priority):
asgi-lifespanlives in[dev]rather than a[test]extra; the ImportError message will need updating if the extra is renamedWhat was tested
pytest tests/test_testing_decisioning.py— 20 passed (12 existing + 8 new)ruff check src/adcp/testing/ tests/test_testing_decisioning.py— cleantest_build_test_client_can_make_requestmakes a real MCPinitializecall through the in-process ASGI stack and asserts HTTP 200asgi_lifespanout ofsys.modulesand asserts the error message firesPre-PR review:
asyncio.to_threadpattern is correct, DX score 5/5 on time-to-hello-worldSession: https://claude.ai/code/session_01UZyqrAkoJPCEz5VLerzxFv
Generated by Claude Code