Skip to content

Ship StoryboardHarness — built-in compliance test harness for adopters via httpx.ASGITransport #662

@bokelley

Description

@bokelley

Summary

Every adopter of `adcp-client-python` who wants to run the compliance storyboard against their own seller in CI has to invent the same harness:

  • Mount the full ASGI app via `build_app()` (or whatever entry point the seller exposes)
  • Drive requests through `httpx.ASGITransport` to exercise the real wire envelope (MCP and A2A)
  • Parse the response, extract `adcp_error` from `structuredContent` (MCP) or `Task.artifacts[0].parts[0].data` (A2A)
  • Run scenarios from the bundled compliance cache against this harness
  • Aggregate pass/fail

This is reinvented in every salesagent test file we've added today (see PR #330's `tests/integration/test_delegate_wire_envelope_cross_transport.py`). It's tedious and prone to drift across adopters.

Proposed surface

```python
from adcp.server.testing import StoryboardHarness

@pytest.fixture
def harness():
return StoryboardHarness(app=build_app(), seller_config=...)

def test_create_media_buy_compliance(harness):
result = harness.run_scenario(
"media_buy_seller/refine_products",
transport="mcp", # or "a2a", or "both"
)
assert result.passed, result.failures

def test_typed_error_translates(harness):
response = harness.invoke(
tool="update_media_buy",
payload={"media_buy_id": "does-not-exist", ...},
transport="a2a",
)
assert response.adcp_error.code == "MEDIA_BUY_NOT_FOUND"
```

The harness:

  • Wraps the ASGI app and provides MCP/A2A transport adapters
  • Reads compliance scenarios from the bundled cache
  • Handles wire-shape envelope unpacking per transport
  • Reports per-scenario pass/fail with the same JSON shape as `adcp storyboard run --json`

Why this matters

  1. Adopters get compliance testing for free — no harness to maintain
  2. Cross-transport contract tests become trivial — single fixture covers both transports
  3. Spec drift detection — when the SDK bumps to a new spec version, every adopter's CI catches behavioral regressions automatically
  4. Onboarding friction drops — "how do I test my seller against AdCP compliance?" has a one-line answer

Reference implementation

PR #330 in bokelley/salesagent (`tests/integration/test_delegate_wire_envelope_cross_transport.py`) is a working version for a single tool. Extending to scenario-level execution is the obvious next step.

Related

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions