Files
temp/features/steps/change_model_coverage_boost_steps.py
freemo a808c395f9 test(coverage): add Behave BDD tests to improve unit test coverage across 53 source modules
Add 53 new .feature files and corresponding step definition files targeting
uncovered lines identified in build/coverage.xml. Fix AmbiguousStep conflicts
in 7 pre-existing step files by disambiguating step text.

New tests cover: ACP clients/facade, actor CLI/config, application container,
ACMS service/strategies, async worker, automation profile CLI, autonomy
guardrail, bridge, change model, config CLI/service, context service,
cross-plan correction, database models, decision service, decomposition
clustering/service, discovery handler, langchain chat provider, langgraph
nodes, materializers, multi-project service, plan apply/CLI/lifecycle/model/
preflight/resume/service, PostgreSQL analyzer, project CLI/context CLI,
provider registry, reactive application/route, repositories, resolver handler,
resource registry service, resume model, retry patterns, sandbox protocol,
server CLI, skill CLI/service, skills registry, subplan execution/service,
system CLI, UKO loader, UoW, and YAML template engine.

Closes #645
2026-03-09 13:01:58 -04:00

202 lines
6.3 KiB
Python

"""Step definitions for change_model_coverage_boost.feature.
Targets uncovered lines in change.py:
- Line 268: DELETE branch of ChangeEntry.has_integrity_hashes
- Lines 487, 491, 499, 503: InvocationTracker Protocol method bodies
- Lines 560, 566, 570, 574, 578: ChangeSetStore Protocol method bodies
"""
from __future__ import annotations
from typing import Any
from behave import given, then, when
from cleveragents.domain.models.core.change import (
ChangeEntry,
ChangeOperation,
ChangeSetStore,
InvocationTracker,
ToolInvocation,
)
__all__: list[str] = []
# ---------------------------------------------------------------------------
# Helpers
# ---------------------------------------------------------------------------
def _base_entry_kwargs() -> dict[str, Any]:
return {
"plan_id": "plan-cov",
"resource_id": "res-cov",
"tool_name": "builtin/file-write",
"path": "src/coverage.py",
}
# Bare subclasses that inherit Protocol default (ellipsis) method bodies.
class _BareInvocationTracker(InvocationTracker):
pass
class _BareChangeSetStore(ChangeSetStore):
pass
# ---------------------------------------------------------------------------
# DELETE has_integrity_hashes (line 268)
# ---------------------------------------------------------------------------
@given('a DELETE ChangeEntry with before_hash "{h}"')
def step_delete_entry_with_before_hash(context: Any, h: str) -> None:
context.entry = ChangeEntry(
**_base_entry_kwargs(),
operation=ChangeOperation.DELETE,
before_hash=h,
)
@given("a DELETE ChangeEntry without before_hash")
def step_delete_entry_without_before_hash(context: Any) -> None:
context.entry = ChangeEntry(
**_base_entry_kwargs(),
operation=ChangeOperation.DELETE,
)
@then("the entry has_integrity_hashes should be true")
def step_entry_integrity_true(context: Any) -> None:
assert context.entry.has_integrity_hashes is True
@then("the entry has_integrity_hashes should be false")
def step_entry_integrity_false(context: Any) -> None:
assert context.entry.has_integrity_hashes is False
# ---------------------------------------------------------------------------
# InvocationTracker Protocol method bodies (lines 487, 491, 499, 503)
# ---------------------------------------------------------------------------
@given("a bare InvocationTracker subclass instance")
def step_bare_invocation_tracker(context: Any) -> None:
context.bare_tracker = _BareInvocationTracker()
@when("I call track on the protocol with a ToolInvocation")
def step_call_track(context: Any) -> None:
inv = ToolInvocation(plan_id="plan-proto", tool_name="test/tool")
context.track_result = context.bare_tracker.track(inv)
@then("track should return None")
def step_track_returns_none(context: Any) -> None:
assert context.track_result is None
@when('I call get_invocations on the protocol with plan_id "{pid}"')
def step_call_get_invocations(context: Any, pid: str) -> None:
context.get_inv_result = context.bare_tracker.get_invocations(pid)
@then("get_invocations should return None")
def step_get_invocations_returns_none(context: Any) -> None:
assert context.get_inv_result is None
@when(
'I call get_invocations_for_skill on the protocol with plan_id "{pid}" and skill "{sk}"'
)
def step_call_get_invocations_for_skill(context: Any, pid: str, sk: str) -> None:
context.get_inv_skill_result = context.bare_tracker.get_invocations_for_skill(
pid, sk
)
@then("get_invocations_for_skill should return None")
def step_get_invocations_for_skill_returns_none(context: Any) -> None:
assert context.get_inv_skill_result is None
@when('I call get_changes on the protocol with plan_id "{pid}"')
def step_call_get_changes(context: Any, pid: str) -> None:
context.get_changes_result = context.bare_tracker.get_changes(pid)
@then("get_changes should return None")
def step_get_changes_returns_none(context: Any) -> None:
assert context.get_changes_result is None
# ---------------------------------------------------------------------------
# ChangeSetStore Protocol method bodies (lines 560, 566, 570, 574, 578)
# ---------------------------------------------------------------------------
@given("a bare ChangeSetStore subclass instance")
def step_bare_changeset_store(context: Any) -> None:
context.bare_store = _BareChangeSetStore()
@when('I call start on the store protocol with plan_id "{pid}"')
def step_call_store_start(context: Any, pid: str) -> None:
context.store_start_result = context.bare_store.start(pid)
@then("start should return None")
def step_store_start_returns_none(context: Any) -> None:
assert context.store_start_result is None
@when(
'I call record on the store protocol with changeset_id "{csid}" and a ChangeEntry'
)
def step_call_store_record(context: Any, csid: str) -> None:
kwargs = _base_entry_kwargs()
kwargs["path"] = "proto.py"
entry = ChangeEntry(
**kwargs,
operation=ChangeOperation.CREATE,
)
context.store_record_result = context.bare_store.record(csid, entry)
@then("record should return None")
def step_store_record_returns_none(context: Any) -> None:
assert context.store_record_result is None
@when('I call get on the store protocol with changeset_id "{csid}"')
def step_call_store_get(context: Any, csid: str) -> None:
context.store_get_result = context.bare_store.get(csid)
@then("protocol get should return None")
def step_store_get_returns_none(context: Any) -> None:
assert context.store_get_result is None
@when('I call get_for_plan on the store protocol with plan_id "{pid}"')
def step_call_store_get_for_plan(context: Any, pid: str) -> None:
context.store_get_for_plan_result = context.bare_store.get_for_plan(pid)
@then("get_for_plan should return None")
def step_store_get_for_plan_returns_none(context: Any) -> None:
assert context.store_get_for_plan_result is None
@when('I call summarize on the store protocol with changeset_id "{csid}"')
def step_call_store_summarize(context: Any, csid: str) -> None:
context.store_summarize_result = context.bare_store.summarize(csid)
@then("summarize should return None")
def step_store_summarize_returns_none(context: Any) -> None:
assert context.store_summarize_result is None