Skip to content

Add deterministic async transport contract tests #302

Description

@Mattsface

Parent: #297
Depends on: #298, #301

Goal

Add deterministic offline tests that lock down the async transport contract and prevent drift from the established 1.x HTTP behavior.

Contract source

#298 is the source of truth for the public async transport contract. This issue should translate that contract into executable tests rather than merely checking that methods exist.

Coverage

Use fake/mocked async HTTP responses to cover at minimum:

HTTP/result behavior

  • 2xx success
  • successful empty response body -> {} through MlbResult
  • non-404 4xx such as 400/403 with strict_http=True -> MlbHttpError
  • non-404 4xx with strict_http=False -> MlbHttpCompatibilityWarning + empty result
  • endpoint-specific 404 handling -> empty MlbResult
  • final 429 behavior after retries
  • final 5xx behavior after retries
  • other final non-2xx behavior
  • structured MlbHttpError status/reason/URL/method and bounded best-effort response context
  • malformed error-response context must not replace the original HTTP error
  • compatibility warning category and caller-oriented call site
  • compatibility warning must not leak response bodies, headers, credentials, or other sensitive context

Timeout, transport, decode, and cancellation

  • timeout -> MlbTimeoutError
  • generic transport failure -> MlbTransportError
  • successful response with invalid JSON -> MlbDecodeError
  • underlying async HTTP-library exception types do not escape as normal public failures
  • caller cancellation propagates as asyncio.CancelledError
  • cancellation is not retried

Retry behavior

For library-owned transport verify:

  • GET-only retries
  • retryable statuses 429, 500, 502, 503, 504
  • equivalent total/connect/read/status retry limits
  • effective 0.5 backoff behavior
  • Retry-After is honored
  • JSON decode and model/parsing failures are not retried
  • retry/backoff yields to the event loop rather than blocking it

Do not require caller-injected clients to adopt the library retry policy.

Lifecycle and ownership

  • library-owned client creation and cleanup
  • explicit aclose()
  • repeated cleanup / idempotent aclose()
  • cleanup on normal exit, exception, and cancellation
  • caller-injected client preservation
  • caller-injected headers/configuration are not silently mutated
  • caller-injected clients are not closed
  • library-owned User-Agent behavior
  • injected-client User-Agent remains caller-controlled

Concurrency

Add deterministic tests proving the #298 concurrency contract:

  • one AsyncMlbDataAdapter / async client can have at least two in-flight requests concurrently on the same event loop
  • concurrent requests maintain independent params, responses, errors, and parsing state
  • cancelling request A does not implicitly cancel unrelated request B
  • failure of request A does not implicitly alter request B unless caller-owned orchestration does so
  • retry/backoff in one request does not block another request from making progress
  • no hidden request fan-out/background task is required for a normal endpoint request

The tests do not need to support or validate cross-thread or cross-event-loop use.

Constraints

  • Tests must not contact the live MLB API
  • Avoid freezing implementation-specific details that are not part of the public contract
  • Reuse the existing public exception hierarchy and model/result semantics
  • Prefer observable behavior assertions over assertions about the selected HTTP library internals

Acceptance criteria

  • Every transport-level behavior explicitly promised by Define the v1.1 async API and transport contract #298 has deterministic offline coverage
  • HTTP status decision table from Define the v1.1 async API and transport contract #298 is covered
  • Timeout, transport, decode, and cancellation mappings are explicitly covered
  • Retry semantics are explicitly covered without freezing unnecessary transport internals
  • Lifecycle, ownership, cleanup, and User-Agent behavior are explicitly covered
  • Same-event-loop concurrent requests are explicitly covered
  • Cancellation independence between concurrent requests is explicitly covered
  • Retry/backoff non-blocking behavior is explicitly covered
  • Failure messages make behavioral regressions easy to diagnose
  • Existing synchronous transport tests remain unchanged/green
  • Test suite is suitable for the supported Python CI matrix

Refs #297
Contract: #298

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions