Files
temp/features/steps/faiss_vector_backend_cov3_steps.py
freemo 31472b5413 test(coverage): add Behave scenarios for 39 under-covered modules
Add Behave feature/step pairs that exercise uncovered branches across handlers, LSP, CLI, and service layers to reach the coverage gate.

ISSUES CLOSED: #1232
2026-03-31 21:47:12 +00:00

343 lines
11 KiB
Python

"""Step definitions for fvcov3 - FAISS vector backend coverage round 3."""
from __future__ import annotations
from typing import Any
from unittest.mock import MagicMock
from behave import given, then, when
from cleveragents.application.services.faiss_vector_backend import (
FAISSVectorBackend,
FAISSVectorIndexBackend,
build_vector_backend,
build_vector_index_backend,
)
from cleveragents.domain.models.acms.index_stubs import InMemoryVectorIndexBackend
from cleveragents.domain.models.acms.stubs import InMemoryVectorBackend
# ---------------------------------------------------------------------------
# Helpers
# ---------------------------------------------------------------------------
def _parse_vector(raw: str) -> list[float]:
return [float(part.strip()) for part in raw.split(",") if part.strip()]
# ---------------------------------------------------------------------------
# Givens
# ---------------------------------------------------------------------------
@given("fvcov3 a mock vector store service")
def step_fvcov3_mock_service(context: Any) -> None:
mock_svc = MagicMock()
mock_svc.acms_search_by_vector.return_value = []
mock_svc.acms_index_embedding.return_value = None
mock_svc.acms_backend_name.return_value = "faiss"
context.fvcov3_service = mock_svc
context.fvcov3_error = None
@given("fvcov3 a FAISSVectorBackend backed by it")
def step_fvcov3_read_backend(context: Any) -> None:
context.fvcov3_read_backend = FAISSVectorBackend(context.fvcov3_service)
@given("fvcov3 a FAISSVectorIndexBackend backed by it")
def step_fvcov3_write_backend(context: Any) -> None:
context.fvcov3_write_backend = FAISSVectorIndexBackend(context.fvcov3_service)
@given("fvcov3 a mock vector store service that returns hits without doc_id")
def step_fvcov3_mock_service_no_docid(context: Any) -> None:
mock_svc = MagicMock()
mock_svc.acms_search_by_vector.return_value = [
{
"content": "some text",
"score": 0.95,
"metadata": {"other_key": "val"}, # no doc_id
},
{
"content": "another",
"score": 0.90,
"metadata": {"doc_id": ""}, # empty doc_id
},
]
context.fvcov3_service = mock_svc
context.fvcov3_error = None
@given("fvcov3 a mock vector store service that returns hits with low scores")
def step_fvcov3_mock_service_low_scores(context: Any) -> None:
mock_svc = MagicMock()
mock_svc.acms_search_by_vector.return_value = [
{
"content": "low score hit",
"score": 0.2,
"metadata": {"doc_id": "doc1"},
},
{
"content": "another low",
"score": 0.3,
"metadata": {"doc_id": "doc2"},
},
]
context.fvcov3_service = mock_svc
context.fvcov3_error = None
@given("fvcov3 a mock vector store service that returns search hits without doc_id")
def step_fvcov3_mock_service_search_no_docid(context: Any) -> None:
mock_svc = MagicMock()
mock_svc.acms_search_by_vector.return_value = [
{
"content": "hit text",
"score": 0.95,
"metadata": {"some_key": "val"}, # no doc_id
},
{
"content": "hit2",
"score": 0.90,
"metadata": {"doc_id": ""}, # empty doc_id
},
]
context.fvcov3_service = mock_svc
context.fvcov3_error = None
@given('fvcov3 a mock vector store service with backend name "{name}"')
def step_fvcov3_mock_service_backend_name(context: Any, name: str) -> None:
mock_svc = MagicMock()
mock_svc.acms_backend_name.return_value = name
context.fvcov3_service = mock_svc
context.fvcov3_error = None
# ---------------------------------------------------------------------------
# Whens
# ---------------------------------------------------------------------------
@when(
'fvcov3 I index embedding with project "{project}" and doc_id "{doc_id}" and vector "{vector}"'
)
def step_fvcov3_index_embedding(
context: Any, project: str, doc_id: str, vector: str
) -> None:
try:
context.fvcov3_write_backend.index_embedding(
project,
doc_id,
_parse_vector(vector),
{"location": "src/foo.py"},
)
context.fvcov3_error = None
except (ValueError, Exception) as exc:
context.fvcov3_error = exc
@when(
'fvcov3 I index embedding with empty project and doc_id "{doc_id}" and vector "{vector}"'
)
def step_fvcov3_index_embedding_empty_project(
context: Any, doc_id: str, vector: str
) -> None:
try:
context.fvcov3_write_backend.index_embedding(
"",
doc_id,
_parse_vector(vector),
{"location": "src/foo.py"},
)
context.fvcov3_error = None
except (ValueError, Exception) as exc:
context.fvcov3_error = exc
@when("fvcov3 I similarity search with empty embedding")
def step_fvcov3_sim_search_empty_embedding(context: Any) -> None:
try:
context.fvcov3_read_backend.similarity_search(
[],
scope=frozenset({"res1"}),
top_k=5,
)
context.fvcov3_error = None
except ValueError as exc:
context.fvcov3_error = exc
@when("fvcov3 I similarity search with top_k {top_k:d}")
def step_fvcov3_sim_search_bad_topk(context: Any, top_k: int) -> None:
try:
context.fvcov3_read_backend.similarity_search(
[1.0, 0.0],
scope=frozenset({"res1"}),
top_k=top_k,
)
context.fvcov3_error = None
except ValueError as exc:
context.fvcov3_error = exc
@when("fvcov3 I perform a valid similarity search")
def step_fvcov3_valid_sim_search(context: Any) -> None:
context.fvcov3_sim_results = context.fvcov3_read_backend.similarity_search(
[1.0, 0.0],
scope=frozenset({"res1"}),
top_k=10,
)
@when(
'fvcov3 I index embedding with project "{project}" and doc_id "{doc_id}" and empty embedding'
)
def step_fvcov3_index_empty_embedding(context: Any, project: str, doc_id: str) -> None:
try:
context.fvcov3_write_backend.index_embedding(
project,
doc_id,
[],
{"location": "src/foo.py"},
)
context.fvcov3_error = None
except ValueError as exc:
context.fvcov3_error = exc
@when(
'fvcov3 I index embedding with metadata having resource_type "{rtype}" but no location'
)
def step_fvcov3_index_with_resource_type(context: Any, rtype: str) -> None:
context.fvcov3_write_backend.index_embedding(
"proj",
"doc1",
[1.0, 0.0],
{"resource_type": rtype},
)
# Capture the content= kwarg passed to acms_index_embedding
call_args = context.fvcov3_service.acms_index_embedding.call_args
context.fvcov3_indexed_content = call_args.kwargs.get("content") or call_args[
1
].get("content")
@when('fvcov3 I index embedding with empty metadata for doc_id "{doc_id}"')
def step_fvcov3_index_empty_metadata(context: Any, doc_id: str) -> None:
context.fvcov3_write_backend.index_embedding(
"proj",
doc_id,
[1.0, 0.0],
{},
)
call_args = context.fvcov3_service.acms_index_embedding.call_args
context.fvcov3_indexed_content = call_args.kwargs.get("content") or call_args[
1
].get("content")
@when('fvcov3 I search similar with empty query embedding in project "{project}"')
def step_fvcov3_search_similar_empty(context: Any, project: str) -> None:
try:
context.fvcov3_write_backend.search_similar(
project,
[],
limit=5,
)
context.fvcov3_error = None
except ValueError as exc:
context.fvcov3_error = exc
@when('fvcov3 I search similar with limit {limit:d} in project "{project}"')
def step_fvcov3_search_similar_bad_limit(
context: Any, limit: int, project: str
) -> None:
try:
context.fvcov3_write_backend.search_similar(
project,
[1.0, 0.0],
limit=limit,
)
context.fvcov3_error = None
except ValueError as exc:
context.fvcov3_error = exc
@when('fvcov3 I search similar with min_relevance {min_rel} in project "{project}"')
def step_fvcov3_search_similar_bad_min_relevance(
context: Any, min_rel: str, project: str
) -> None:
min_relevance = float(min_rel)
try:
results = context.fvcov3_write_backend.search_similar(
project,
[1.0, 0.0],
limit=5,
min_relevance=min_relevance,
)
context.fvcov3_search_results = results
context.fvcov3_error = None
except ValueError as exc:
context.fvcov3_error = exc
@when("fvcov3 I call build_vector_backend")
def step_fvcov3_call_build_vector_backend(context: Any) -> None:
context.fvcov3_build_result = build_vector_backend(context.fvcov3_service)
@when("fvcov3 I call build_vector_index_backend")
def step_fvcov3_call_build_vector_index_backend(context: Any) -> None:
context.fvcov3_build_result = build_vector_index_backend(context.fvcov3_service)
# ---------------------------------------------------------------------------
# Thens
# ---------------------------------------------------------------------------
@then('fvcov3 the error message should contain "{fragment}"')
def step_fvcov3_assert_error_message(context: Any, fragment: str) -> None:
assert context.fvcov3_error is not None, "Expected an error but none was raised"
assert fragment in str(context.fvcov3_error), (
f"Expected '{fragment}' in error message, got: {context.fvcov3_error}"
)
@then("fvcov3 the similarity search results should be empty")
def step_fvcov3_assert_sim_results_empty(context: Any) -> None:
assert context.fvcov3_sim_results == [], (
f"Expected empty results, got {context.fvcov3_sim_results}"
)
@then('fvcov3 the indexed content should be "{expected}"')
def step_fvcov3_assert_indexed_content(context: Any, expected: str) -> None:
assert context.fvcov3_indexed_content == expected, (
f"Expected content '{expected}', got '{context.fvcov3_indexed_content}'"
)
@then("fvcov3 the search similar results should be empty")
def step_fvcov3_assert_search_similar_empty(context: Any) -> None:
assert context.fvcov3_search_results == [], (
f"Expected empty results, got {context.fvcov3_search_results}"
)
@then("fvcov3 the result should be an InMemoryVectorBackend")
def step_fvcov3_assert_inmemory_vector(context: Any) -> None:
assert isinstance(context.fvcov3_build_result, InMemoryVectorBackend), (
f"Expected InMemoryVectorBackend, got {type(context.fvcov3_build_result)}"
)
@then("fvcov3 the result should be an InMemoryVectorIndexBackend")
def step_fvcov3_assert_inmemory_index(context: Any) -> None:
assert isinstance(context.fvcov3_build_result, InMemoryVectorIndexBackend), (
f"Expected InMemoryVectorIndexBackend, got {type(context.fvcov3_build_result)}"
)