6eb9c41407
CI / build (pull_request) Successful in 44s
CI / helm (pull_request) Successful in 53s
CI / lint (pull_request) Successful in 59s
CI / quality (pull_request) Successful in 1m0s
CI / push-validation (pull_request) Successful in 44s
CI / typecheck (pull_request) Successful in 1m9s
CI / security (pull_request) Successful in 1m10s
CI / unit_tests (pull_request) Successful in 5m47s
CI / docker (pull_request) Successful in 1m34s
CI / integration_tests (pull_request) Successful in 8m33s
CI / coverage (pull_request) Successful in 9m9s
CI / status-check (pull_request) Successful in 4s
Address reviewer blocking issues on PR #11003: 1. Remove unused `import os` and inner `MagicMock` re-import from the gemini fallback step definitions (ruff F401). 2. Remove `@tdd_expected_fail` from the TDD feature now that the registry fix makes the scenario pass; keep `@tdd_issue` / `@tdd_issue_4750` as permanent regression markers. 3. Rewrite three feature step texts to use the env-var step defs that already exist in `provider_registry_steps.py` instead of duplicating them (drops the `env var` phrasing the original feature used and that had no matching step def). 4. Add `"gemini"` to `FallbackSelector.DEFAULT_FALLBACK_ORDER` after `"google"` so the actor-configured fallback chain mirrors the registry-level fix. 5. Rename three of the new feature/step pairs to avoid ambiguous-step collisions that crashed every behave-parallel worker at module-load time (the root cause of the "8 features errored, 0 scenarios" pattern): - `the result should be ProviderType "GEMINI"` collided with `cli_steps.py:138`'s `@then("the result should be {expected}")`; renamed to `the gemini fallback default should be ProviderType "GEMINI"`. - `the result should be None` had the same collision; renamed to `the clean gemini registry default should be None`. - `@given("I have the ProviderRegistry class")` was duplicated in `provider_registry_steps.py:186`; the duplicate is removed and the existing definition is reused. ISSUES CLOSED: #10906
150 lines
4.9 KiB
Python
150 lines
4.9 KiB
Python
"""Step definitions for fallback_gemini_provider.feature.
|
|
|
|
Verifies that ProviderType.GEMINI is present in
|
|
ProviderRegistry.FALLBACK_ORDER and selected as the default provider when
|
|
only the Gemini API key is configured.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from typing import Any
|
|
|
|
from behave import given, then, when # type: ignore[import-untyped]
|
|
|
|
from cleveragents.providers.registry import (
|
|
ProviderRegistry,
|
|
ProviderType,
|
|
)
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Helper
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
def _make_gemini_settings(
|
|
openai: str | None = None,
|
|
anthropic: str | None = None,
|
|
google: str | None = None,
|
|
gemini: str | None = None,
|
|
azure: str | None = None,
|
|
openrouter: str | None = None,
|
|
cohere: str | None = None,
|
|
groq: str | None = None,
|
|
together: str | None = None,
|
|
default_provider: str | None = None,
|
|
) -> object:
|
|
"""Return a minimal Settings-like mock for BDD steps."""
|
|
from unittest.mock import MagicMock
|
|
|
|
settings = MagicMock()
|
|
settings.openai_api_key = openai
|
|
settings.anthropic_api_key = anthropic
|
|
settings.google_api_key = google
|
|
settings.gemini_api_key = gemini
|
|
settings.azure_api_key = azure
|
|
settings.openrouter_api_key = openrouter
|
|
settings.cohere_api_key = cohere
|
|
settings.groq_api_key = groq
|
|
settings.together_api_key = together
|
|
settings.default_provider = default_provider
|
|
settings.default_model = None
|
|
return settings
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Given
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
@given('a registry with only gemini API key set to "{key}"')
|
|
def step_gemini_only_registry(context: Any, key: str) -> None:
|
|
settings = _make_gemini_settings(gemini=key)
|
|
context.gemini_registry = ProviderRegistry(settings=settings)
|
|
|
|
|
|
@given("a gemini-registry with no API keys configured")
|
|
def step_no_keys_gemini_registry(context: Any) -> None:
|
|
context.gemini_registry = ProviderRegistry(settings=_make_gemini_settings())
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# When
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
@when("I check the FALLBACK_ORDER contents")
|
|
def step_check_fallback_order(context: Any) -> None:
|
|
"""Read the FALLBACK_ORDER class variable."""
|
|
context.fallback_order = list(ProviderRegistry.FALLBACK_ORDER)
|
|
|
|
|
|
@when("I request the default provider type")
|
|
def step_request_default_provider_type(context: Any) -> None:
|
|
result = context.gemini_registry.get_default_provider_type()
|
|
context.gemini_default = result
|
|
|
|
|
|
@when("I iterate through FALLBACK_ORDER and find the first configured provider")
|
|
def step_iterate_fallback_order(context: Any) -> None:
|
|
"""Manually walk FALLBACK_ORDER to verify GEMINI is checked."""
|
|
found = None
|
|
for pt in ProviderRegistry.FALLBACK_ORDER:
|
|
if context.gemini_registry.is_provider_configured(pt):
|
|
found = pt
|
|
break
|
|
context.fallback_iteration_result = found
|
|
|
|
|
|
@when("I request the default provider type from a clean registry")
|
|
def step_request_default_from_clean(context: Any) -> None:
|
|
result = context.gemini_registry.get_default_provider_type()
|
|
context.clean_default = result
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Then
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
@then("GEMINI should be present in the fallback order")
|
|
def step_gemini_in_fallback_order(context: Any) -> None:
|
|
assert ProviderType.GEMINI in context.fallback_order, (
|
|
f"Expected GEMINI in FALLBACK_ORDER={context.fallback_order}"
|
|
)
|
|
|
|
|
|
@then("OPENAI should still be first in the order")
|
|
def step_openai_first(context: Any) -> None:
|
|
assert context.fallback_order[0] == ProviderType.OPENAI, (
|
|
f"Expected OPENAI first, got {context.fallback_order[0]}"
|
|
)
|
|
|
|
|
|
@then("ANTHROPIC should still be second in the order")
|
|
def step_anthropic_second(context: Any) -> None:
|
|
assert context.fallback_order[1] == ProviderType.ANTHROPIC, (
|
|
f"Expected ANTHROPIC second, got {context.fallback_order[1]}"
|
|
)
|
|
|
|
|
|
@then('the gemini fallback default should be ProviderType "GEMINI"')
|
|
def step_result_is_gemini(context: Any) -> None:
|
|
assert context.gemini_default == ProviderType.GEMINI, (
|
|
f"Expected GEMINI, got {context.gemini_default!r}"
|
|
)
|
|
|
|
|
|
@then("GEMINI should be the first configured provider found")
|
|
def step_gemini_first_configured(context: Any) -> None:
|
|
assert context.fallback_iteration_result == ProviderType.GEMINI, (
|
|
f"Expected GEMINI as first found, got {context.fallback_iteration_result!r}"
|
|
)
|
|
|
|
|
|
@then("the clean gemini registry default should be None")
|
|
def step_result_is_none(context: Any) -> None:
|
|
assert context.clean_default is None, (
|
|
f"Expected None, got {context.clean_default!r}"
|
|
)
|