Skip to content

refactor(testing): replace dict[str, Any] result bags with typed models - #910

Merged
tcoratger merged 1 commit into
leanEthereum:mainfrom
tcoratger:refactor/typed-output-models
Jun 10, 2026
Merged

refactor(testing): replace dict[str, Any] result bags with typed models#910
tcoratger merged 1 commit into
leanEthereum:mainfrom
tcoratger:refactor/typed-output-models

Conversation

@tcoratger

Copy link
Copy Markdown
Collaborator

Motivation

Two spots returned untyped dict[str, Any] bags with magic string keys, while every other fixture in the package uses a typed model:

  • API endpoint handlers returned dict[str, Any] keyed by "expected_status_code", "expected_content_type", "expected_body", read back positionally in the generator. A handler that forgot a key would only fail at the read site.
  • The justifiability fixture stored its result as a hand-written camelCase dict ({"delta": ..., "isJustifiable": ...}).

What this does

  • Adds EndpointResponseContract(status_code, content_type, body) — the endpoint handler signature is now typed, and a handler that omits a field is caught at construction. This is internal plumbing (the contract feeds the same three ApiEndpointFixture fields), so emitted fixtures are unchanged.
  • Adds JustifiabilityOutput(delta, is_justifiable) — the camelCase isJustifiable key now comes from the model alias, and the values are validated. The body/response payloads keep their own API-defined snake_case keys untouched.

Byte-equivalence

Both suites were filled before and after and diffed:

114 passed
diff -rq <golden> <new>  ->  IDENTICAL: no vector churn

The endpoint contract feeds the same fixture fields, and JustifiabilityOutput serializes is_justifiable through the camelCase alias exactly as the hand-written dict did.

Testing

  • just check passes (lint, format, ty, codespell, mdformat).
  • Fill of tests/consensus/lstar/api + tests/consensus/lstar/state_transition (114 fixtures) is byte-identical to the pre-change output.

🤖 Generated with Claude Code

Two spots returned untyped dict[str, Any] bags with magic string keys
while every other fixture uses a typed model.

The API endpoint handlers returned a dict keyed by expected_status_code,
expected_content_type, and expected_body, read back positionally in the
generator.
Introduce EndpointResponseContract so the handler signature is typed and a
handler that forgets a field is caught at construction.
This is internal plumbing, so the emitted fixture fields are unchanged.

The justifiability fixture stored its result as a hand-written camelCase
dict.
Introduce JustifiabilityOutput so the camelCase keys come from the model
and the delta and verdict are validated.

Both changes are byte-identical on every emitted vector: the endpoint
contract feeds the same fixture fields, and the output model serializes
isJustifiable through the camelCase alias exactly as before.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@tcoratger
tcoratger merged commit bb1d020 into leanEthereum:main Jun 10, 2026
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant