Files
temp/features/steps/postgresql_analyzer_coverage_boost_steps.py
T
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

205 lines
7.0 KiB
Python

"""Step definitions for PostgreSQLAnalyzer coverage-boost scenarios.
Targets uncovered lines in postgresql_analyzer.py:
- Lines 112-116: exception handler in analyze()
- Line 135: duplicate CREATE SCHEMA deduplication
- Line 198: _extract_tables with tables_seen=None
- Line 285: CREATE VIEW without trailing semicolon
- Lines 297-302: schema-qualified CREATE VIEW with uko:contains
"""
from __future__ import annotations
from unittest.mock import patch
from behave import given, then, use_step_matcher, when
from behave.runner import Context
use_step_matcher("re")
from cleveragents.domain.models.acms.postgresql_analyzer import ( # noqa: E402
PostgreSQLAnalyzer,
)
__all__: list[str] = []
_SAMPLE_URI = "uko://test/coverage-boost"
# ---------------------------------------------------------------------------
# Given
# ---------------------------------------------------------------------------
@given(r"a fresh PostgreSQLAnalyzer instance")
def step_given_fresh_postgresql_analyzer(context: Context) -> None:
context.analyzer = PostgreSQLAnalyzer()
context.triples = []
# ---------------------------------------------------------------------------
# When
# ---------------------------------------------------------------------------
@when(r"I analyze DDL with duplicate schemas:")
def step_when_analyze_ddl_duplicate_schemas(context: Context) -> None:
context.triples = context.analyzer.analyze(context.text, _SAMPLE_URI)
@when(r"I analyze DDL that triggers an internal parse error")
def step_when_analyze_ddl_with_parse_error(context: Context) -> None:
"""Force an exception inside _extract_tables to exercise lines 112-116."""
with (
patch.object(
context.analyzer,
"_extract_tables",
side_effect=RuntimeError("simulated parse failure"),
),
# Capture the log output to verify the warning was emitted.
patch(
"cleveragents.domain.models.acms.postgresql_analyzer.logger"
) as mock_logger,
):
context.triples = context.analyzer.analyze(
"CREATE SCHEMA testschema;\nCREATE TABLE t (id INT);\n",
_SAMPLE_URI,
)
context.mock_logger = mock_logger
@when(r"I call _extract_tables directly without tables_seen on:")
def step_when_call_extract_tables_directly(context: Context) -> None:
"""Call _extract_tables with tables_seen=None to hit line 198."""
context.triples = context.analyzer._extract_tables(
context.text,
_SAMPLE_URI,
set(),
None,
)
@when(r"I analyze DDL with a view missing its semicolon:")
def step_when_analyze_ddl_view_no_semicolon(context: Context) -> None:
context.triples = context.analyzer.analyze(context.text, _SAMPLE_URI)
@when(r"I analyze DDL with a schema-qualified view:")
def step_when_analyze_ddl_schema_qualified_view(context: Context) -> None:
context.triples = context.analyzer.analyze(context.text, _SAMPLE_URI)
# ---------------------------------------------------------------------------
# Then
# ---------------------------------------------------------------------------
@then(r"exactly (?P<count>\d+) Schema type triple should exist")
def step_then_exactly_n_schema_triples(context: Context, count: str) -> None:
count_int = int(count)
actual = sum(
1
for t in context.triples
if t.predicate == "rdf:type" and t.object_uri == "uko-data:Schema"
)
assert actual == count_int, (
f"Expected {count_int} Schema type triple(s), got {actual}.\n"
f"Triples: {context.triples}"
)
@then(
r'the result triples should contain predicate "(?P<pred>[^"]+)" with value "(?P<val>[^"]+)"'
)
def step_then_result_contains_pred_value(context: Context, pred: str, val: str) -> None:
found = any(t.predicate == pred and t.object_value == val for t in context.triples)
assert found, (
f"No triple with predicate={pred!r} object_value={val!r}.\n"
f"Triples: {context.triples}"
)
@then(
r'the result triples should contain predicate "(?P<pred>[^"]+)" with uri "(?P<uri>[^"]+)"'
)
def step_then_result_contains_pred_uri(context: Context, pred: str, uri: str) -> None:
found = any(t.predicate == pred and t.object_uri == uri for t in context.triples)
assert found, (
f"No triple with predicate={pred!r} object_uri={uri!r}.\n"
f"Triples: {context.triples}"
)
@then(r'the result triples should contain predicate "(?P<pred>[^"]+)" present')
def step_then_result_contains_pred(context: Context, pred: str) -> None:
found = any(t.predicate == pred for t in context.triples)
assert found, f"No triple with predicate={pred!r}.\nTriples: {context.triples}"
@then(r"the partial results should be returned without raising")
def step_then_partial_results_returned(context: Context) -> None:
# analyze() should have caught the exception and returned a list
assert isinstance(context.triples, list), (
f"Expected a list, got {type(context.triples).__name__}"
)
@then(r"the parse error should have been logged as a warning")
def step_then_parse_error_logged(context: Context) -> None:
mock_logger = context.mock_logger
mock_logger.warning.assert_called_once()
call_args = mock_logger.warning.call_args
assert "parse error" in call_args[0][0].lower(), (
f"Expected 'parse error' in warning message, got: {call_args[0][0]!r}"
)
@then(r'the direct extraction should produce Table triples for "(?P<table_name>[^"]+)"')
def step_then_direct_extraction_produces_table(
context: Context, table_name: str
) -> None:
has_table_type = any(
t.predicate == "rdf:type" and t.object_uri == "uko-data:Table"
for t in context.triples
)
has_label = any(
t.predicate == "rdfs:label" and t.object_value == table_name
for t in context.triples
)
assert has_table_type, (
f"No rdf:type uko-data:Table triple found.\nTriples: {context.triples}"
)
assert has_label, (
f"No rdfs:label={table_name!r} triple found.\nTriples: {context.triples}"
)
@then(r'the viewDefinition value should contain "(?P<fragment>[^"]+)"')
def step_then_view_definition_contains(context: Context, fragment: str) -> None:
found = any(
t.predicate == "uko-data:viewDefinition" and fragment in t.object_value
for t in context.triples
)
assert found, (
f"No uko-data:viewDefinition triple containing {fragment!r}.\n"
f"Triples: {context.triples}"
)
@then(
r'the result triples should contain predicate "(?P<pred>[^"]+)" '
r'linking schema "(?P<schema>[^"]+)" to view "(?P<view>[^"]+)"'
)
def step_then_result_contains_schema_view_link(
context: Context, pred: str, schema: str, view: str
) -> None:
found = any(
t.predicate == pred and schema in t.subject_uri and view in t.object_uri
for t in context.triples
)
assert found, (
f"No triple with predicate={pred!r} linking schema containing "
f"{schema!r} to view containing {view!r}.\n"
f"Triples: {context.triples}"
)