Skip to content

tests: cover OpenAI provider gaps — key resolution, Qwen XML salvage, stream edges#196

Open
ayobamiseun wants to merge 1 commit into
andrewyng:mainfrom
ayobamiseun:tests/openai-provider-gaps
Open

tests: cover OpenAI provider gaps — key resolution, Qwen XML salvage, stream edges#196
ayobamiseun wants to merge 1 commit into
andrewyng:mainfrom
ayobamiseun:tests/openai-provider-gaps

Conversation

@ayobamiseun

Copy link
Copy Markdown

What

Adds tests/test_openai_provider.py (20 tests). The Anthropic and Gemini providers each have a dedicated test module (test_anthropic_provider.py, test_gemini_provider.py), but coworker/providers/openai_provider.py was only covered incidentally — test_providers.py handles complete/stream basics and the param-fix retries, test_provider_router.py handles JSON-form tool-call salvage. This fills what neither reaches:

  • Key resolution & client bootstrap (mirrors the existing Anthropic/Gemini tests): resolve_api_key env-over-SecretStore precedence and empty-profile fallbacks; _ensure_client raising the no-key RuntimeError; api_key/base_url plumbed to the SDK client (the Ollama/compat path).
  • The Qwen/Hermes XML tool-call template (salvage path 1b, <function=…><parameter=…>openai_provider.py:296-307), which had no coverage anywhere: happy path per the template in the code comment, verbatim free-text parameters (file content with newlines), unambiguous-JSON coercion, unknown-name filtering, schema-less acceptance, multi-block renumbering, plus _coerce_param directly.
  • Salvage gating inside complete()/stream(): salvage fires only when tools were offered and no structured calls came back; structured tool_calls always win over tool-shaped text; streamed text deltas still surface live before the final turn swaps in the recovered calls.
  • Stream edge cases: unparseable accumulated arguments surface as {"_raw": …}; parallel calls come out ordered by index with empty args as {}; choice-less keep-alive/usage chunks from compat servers are skipped; and the reasoning attribute variant (xAI/OpenRouter — distinct from reasoning_content) on both stream() and complete().

Tests-only change; no production code touched. Fakes follow the established SDK-free SimpleNamespace pattern from test_providers.py.

Verification

$ .venv/bin/python -m pytest tests/test_openai_provider.py -q
20 passed in 0.54s

$ .venv/bin/python -m pytest tests -q
909 passed, 1 skipped in 42.76s

No screenshots — no UI change.

… stream edges

The Anthropic and Gemini providers each have a dedicated test module, but
openai_provider.py was only covered incidentally by test_providers.py
(complete/stream basics, param-fix retries) and test_provider_router.py
(JSON-form tool-call salvage). This adds tests/test_openai_provider.py for
what neither reaches:

- resolve_api_key precedence (env over SecretStore) and _ensure_client
  (no-key RuntimeError; api_key/base_url plumbed to the SDK client) —
  mirroring the existing Anthropic/Gemini tests.
- The Qwen/Hermes XML tool-call template (salvage path 1b:
  <function=...><parameter=...>), which had no coverage at all: happy path,
  verbatim free-text params, JSON coercion, unknown-name filtering,
  schema-less acceptance, multi-block renumbering, and _coerce_param.
- Salvage gating inside complete()/stream(): salvage fires only when tools
  were offered and no structured calls came back; structured calls always
  win; streamed text deltas still surface live before the final turn swaps
  in the recovered calls.
- Stream edge cases: unparseable accumulated args surface as _raw,
  parallel calls ordered by index, choice-less keep-alive chunks skipped,
  and the xAI/OpenRouter reasoning attribute variant.

Full backend suite: 909 passed, 1 skipped.
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