Test: pin the dev server eval-set read API at the HTTP level - #208
Open
AmaadMartin wants to merge 1 commit into
Open
Test: pin the dev server eval-set read API at the HTTP level#208AmaadMartin wants to merge 1 commit into
AmaadMartin wants to merge 1 commit into
Conversation
The dev UI browses eval data through six routes on DevServer, and none of them had an HTTP-level test. A rename, a response-shape change, or a status-code drift could ship unnoticed. These tests drive the real FastAPI app with TestClient over a real InMemoryEvalSetsManager, and assert the exact status code and detail string on every error path.
This was referenced Aug 10, 2026
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.
Please ensure you have read the contribution guide before creating a pull request.
Link to Issue or Description of Change
Link to an existing issue (if applicable):
N/A
Or, if no issue exists, describe the change:
Problem: The developer UI browses eval data through six routes on
DevServer: list eval sets (canonical and deprecated), list the eval case ids in a set, and get, update or delete a single eval case. No test drives those routes over HTTP. A route rename, a response-shape change, or a status-code drift ships silently.Solution: I added 13 tests to the existing
# Eval endpoint plumbingsection oftests/unittests/cli/test_fast_api.py. They drive the real FastAPI app withTestClientover a realInMemoryEvalSetsManager, so nothing on the path is mocked. Every error path asserts the exact status code and the exactdetailstring. No file undersrc/changes.Two handlers behave in a way that looks like a defect.
list_evals_in_eval_setanswers 400 for a missing eval set while its get, put and delete siblings answer 404.list_eval_setsreturns an empty list for an unknown app instead of 404. The tests pin today's behaviour and carry an inline comment, because changing a public status code is a separate change.Collision check: I listed the 100 open pull requests on this fork and read the diff of every one that touches
tests/unittests/cli/test_fast_api.pyorsrc/google/adk/cli/dev_server.py. No open pull request adds HTTP tests for these routes. Three overlap:EvalCaseandInvocationimports from this file as unused. These tests use both. Its branch is 73 commits behindmainand is itself stacked on Test: Add explicit asyncio markers to the last unmarked async tests and fixtures #146, so I branched frommaininstead. If Test: remove the unused create_test_eval_set fixture from test_fast_api.py #178 merges first, restore those two imports.xfailin this section and repairs theUserEvalSetname indev_server.py. It does not touch the lines I add.Testing Plan
Please describe the tests that you ran to verify your changes. This is required for all PRs that are not small documentation or typo fixes.
Unit Tests:
The 13 tests expand to 17 items, because four are parametrized over two cases. The file held 112 items before and holds 129 now. The existing pass, skip and xfail counts do not change, and no new warning appears.
Mutation results. The
devextra installs no coverage plugin, so I proved the tests instead of measuring them. I broke one production line per run and confirmed the matching test fails. All 11 mutations were killed, and together they cover all 17 new items.sorted()inlist_evals_in_eval_set..._returns_sorted_eval_case_idsassert ['case_b', 'case_a'] == ['case_a', 'case_b']list_evals_in_eval_setraises 404, not 400..._unknown_eval_set_is_a_client_errorassert 404 == 400list_eval_setsreverses the ids..._returns_created_eval_set_idsassert {'evalSetIds': ['es_two', 'es_one']} == {'evalSetIds': ['es_one', 'es_two']}list_eval_setsraises 404 on an empty result..._is_empty_for_app_without_eval_setsassert 404 == 200..._legacy_returns_a_bare_id_listResponseValidationError: Input should be a valid stringget_evalnever returns the found casetest_get_eval_case_returns_the_eval_case(2 items)assert 404 == 200get_evalreports a generic detail..._returns_404_for_missing_eval_set_or_eval_case(2 items)assert 'not found.' == 'Eval set `es_one` or Eval `missing` not found.'update_evalskips the id mismatch check..._rejects_eval_id_mismatchassert 200 == 400update_evalnever writes to the manager..._replaces_the_stored_eval_case,..._returns_404_...(3 items)assert 'user text for case_a' == 'replacement text'delete_evalnever deletes..._removes_it_from_the_eval_set,..._returns_404_...(3 items)assert ['case_a', 'case_b'] == ['case_a']EvalCasedrops the conversation xor scenario check..._rejects_a_body_without_a_conversationassert 200 == 422Manual End-to-End (E2E) Tests:
TestClientalready exercises the real routing table, the real pydantic serialization and the realInMemoryEvalSetsManager, so the automated tests are the end-to-end proof. To reproduce:I recorded the expected bodies by driving the real app first, then wrote the assertions from what it returned.
Checklist
CI note
Every test job passes: Unit Tests on Python 3.10 through 3.14, A2A v0.3 Tests on 3.10 through 3.14, and Mypy Check on 3.10 through 3.13.
Pre-commit Linterfails, and it fails for a reason this branch did not cause. Theupdate-constraintshook rewritesconstraints-3.11.txtandconstraints-3.12.txtduring the run, so pre-commit reports "files were modified by this hook". The same job fails onmainitself at commit 352d11d, and on the other open pull requests. This branch touches nopyproject.tomland no constraints file. Running pre-commit against the one file I changed passes every hook: