forked from HAL9000/cleveragents-core
02250473ad
Fix all failing CI quality gates (lint, unit_tests, format) without suppressing any quality enforcement. Root causes and fixes: 1. Format: features/steps/plan_namespaced_name_tdd_steps.py had trailing whitespace; fixed by running ruff format. 2. Unit tests - A2A JSON-RPC 2.0 migration (commit9c6d6915) renamed A2aRequest fields (operation→method, request_id→id, a2a_version→jsonrpc) and A2aResponse fields (status+data→result, request_id→id) but did not update all step files and feature files: - a2a_jsonrpc_wire_format_steps.py: added use_step_matcher('re') and reset to 'parse' at end to prevent parallel test interference - a2a_facade_wiring_steps.py: updated operation= to method=, .status/.data to .result - a2a_facade_steps.py: updated request_id→id, a2a_version→jsonrpc, A2aResponse(request_id=..., status=...) to new API - m6_facade_steps.py: updated all old API usage - devcontainer_cleanup_steps.py: updated A2aRequest(operation=...) - plan_prompt_command_steps.py: updated A2aRequest(operation=...) - wf03_plan_prompt_confidence_steps.py: updated A2aRequest(operation=...) - consolidated_misc.feature: updated old A2aRequest/A2aResponse scenarios 3. Unit tests - Session CLI output changed (commit0d5d9cf0and others): - 'Session Created' → 'Session created' (lowercase) - 'Session Details' → 'Session Summary' - 'Sessions (N total)' → 'Sessions' - session list JSON: top-level 'total' → nested 'summary.total' - Fixed in: session_cli.feature, session_cli_coverage_boost.feature, session_cli_uncovered_branches.feature, session_list_error.feature, tdd_session_create_persist_steps.py 4. Unit tests - Plan list output changed (commit1a07a891): - 'V3 Lifecycle Plans' → 'Plans' - 'Lifecycle Plans' → 'Plans' - Name column removed (restored in source) - Invariants column removed (restored in source) - Project truncation removed (restored in source) - Fixed in: plan_cli_cancel_revert_coverage.feature, plan_lifecycle_cli_coverage.feature, plan_cli_coverage_boost_steps.py, plan.py (source code restored) 5. Unit tests - Plan apply command now requires ULID (commit300a5d6d): - plan_cli_coverage_r3.feature: updated 'PLAN-001' to valid ULID - plan_cli_coverage_r3_steps.py: added --yes flag, added new step for no-eligible-plans path 6. Unit tests - Various source code bugs: - ThoughtBlock: converted from @dataclass to Pydantic BaseModel (architecture test requires all dataclasses to use Pydantic) - session.py: added DatabaseError handling to export, import, tell commands - database.py: fixed rollback_to() to reuse checkpoint connection for writes - database.py: added _get_checkpoint_conn() helper - check-tls-cert.py: fixed SSLCertVerificationError.reason AttributeError 7. Unit tests - Test step bugs: - error_recovery_coverage_boost_steps.py: fixed invalid ULID _PLAN_ID - session_service_coverage_steps.py: fixed 'sha256:' prefix bug in checksum - database_models_new_coverage_steps.py: added 'name' field to session mock - async_audit_recording_steps.py: fixed Settings(audit_async=False) via env var - coverage_threshold_config_steps.py: added --coverage-min pattern support - m5_acms_smoke_steps.py: updated usage hint text - actor_cli_yaml_steps.py: updated 'Removed actor' → 'Actor removed' - aimodelscredentials_steps.py: set context.imported_class in import step - domain_base_model.feature: added missing 'When I examine model_config' step - tui_first_run_steps.py: fixed module reload to restore cleveragents.tui.* modules after test (prevented patch interference in subsequent tests) - tui_first_run_steps.py: added set_search('') step for empty string - resource_handler_base_coverage_r3_steps.py: use _MinimalHandler instead of DatabaseResourceHandler for NotImplementedError tests - resource_handler_crud.feature: updated to test new DatabaseHandler behavior - resource_handler_sandbox.feature: updated to test new DatabaseHandler behavior - tdd_json_decode_crash_persistence.feature: fixed @tdd_bug → @tdd_issue tags 8. Parallel test interference: - All step files using use_step_matcher('re') now reset to 'parse' at end to prevent global matcher state leaking to subsequent step files
209 lines
7.1 KiB
Python
209 lines
7.1 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}"
|
|
)
|
|
|
|
|
|
# Reset step matcher to parse (default) so subsequent step files are not affected
|
|
use_step_matcher("parse")
|