Files
cleveragents-core/features/steps/semantic_validation_suite_steps.py
T
CoreRasurae 7e6f6fae37
CI / benchmark-publish (pull_request) Has been skipped
CI / lint (pull_request) Successful in 12s
CI / build (pull_request) Successful in 15s
CI / quality (pull_request) Successful in 17s
CI / typecheck (pull_request) Successful in 31s
CI / security (pull_request) Successful in 31s
CI / unit_tests (pull_request) Successful in 1m46s
CI / docker (pull_request) Successful in 38s
CI / integration_tests (pull_request) Successful in 2m52s
CI / coverage (pull_request) Successful in 3m41s
CI / benchmark-regression (pull_request) Successful in 23m24s
CI / lint (push) Successful in 14s
CI / build (push) Successful in 15s
CI / quality (push) Successful in 17s
CI / typecheck (push) Successful in 33s
CI / benchmark-regression (push) Has been skipped
CI / security (push) Successful in 35s
CI / unit_tests (push) Successful in 2m13s
CI / docker (push) Successful in 38s
CI / integration_tests (push) Successful in 2m58s
CI / coverage (push) Successful in 3m44s
CI / benchmark-publish (push) Successful in 13m19s
test(validation): add semantic validation suites
Add comprehensive semantic validation test suites covering five
new fixture categories: language porting mismatches, dependency
graph violations, API surface changes, cross-file symbols, and
circular import detection.

New BDD scenarios (38) exercise all six built-in rules against
fixture-driven inputs.  Robot Framework integration tests (11)
validate end-to-end rule execution via the SemanticValidationService.
ASV benchmarks (6 suites) establish performance baselines for
batch validation throughput and per-rule latency.

Files added:
- features/fixtures/validation/{language_porting_mismatches,
  dependency_graph_violations, api_surface_changes,
  cross_file_symbols, circular_import_detection}.json
- features/semantic_validation_suite.feature
- features/steps/semantic_validation_suite_steps.py
- robot/semantic_validation_suite.robot
- robot/helper_semantic_validation_suite.py
- benchmarks/semantic_validation_suite_bench.py
- docs/reference/semantic_validation_coverage.md

All 11 nox sessions pass (lint, format, typecheck, security_scan,
dead_code, unit_tests, integration_tests, docs, build, benchmark,
coverage_report).  Coverage remains at 97%.

ISSUES CLOSED: #316
2026-03-02 22:05:53 +00:00

174 lines
5.7 KiB
Python

"""Step definitions for semantic validation suite scenarios.
Loads JSON fixture files covering language-porting mismatches, dependency
graph violations, API surface changes, cross-file symbol resolution,
and circular import detection. Runs the appropriate semantic validation
rule against each fixture and asserts the expected outcome.
Uses :mod:`features.fixtures.validation.suite_helpers` for shared
loading, lookup, and verification logic.
"""
from __future__ import annotations
import sys
from pathlib import Path
from typing import TYPE_CHECKING, Any
from behave import given, then, when
if TYPE_CHECKING:
from behave.runner import Context
# Ensure the fixture helpers package is importable
_FIXTURES_PARENT = str(Path(__file__).resolve().parents[1] / "fixtures" / "validation")
if _FIXTURES_PARENT not in sys.path:
sys.path.insert(0, _FIXTURES_PARENT)
from suite_helpers import ( # noqa: E402
API_FILENAME,
CIRCULAR_FILENAME,
CROSS_FILE_FILENAME,
DEPENDENCY_FILENAME,
PORTING_FILENAME,
find_fixture,
load_fixtures,
validate_fixture_schema,
verify_fixture_result,
)
# ---------------------------------------------------------------------------
# Lazy fixture cache (FLAW-3 fix: avoid module-level loading)
# ---------------------------------------------------------------------------
_fixture_cache: dict[str, list[dict[str, Any]]] = {}
def _get_fixtures(filename: str) -> list[dict[str, Any]]:
"""Lazily load and cache fixtures by filename."""
if filename not in _fixture_cache:
_fixture_cache[filename] = load_fixtures(filename)
return _fixture_cache[filename]
# ---------------------------------------------------------------------------
# Background
# ---------------------------------------------------------------------------
@given("a semantic validation suite test environment")
def step_suite_env(context: Context) -> None:
context.suite_fixture = None
context.suite_result = None
# ---------------------------------------------------------------------------
# Given steps - load individual fixtures
# ---------------------------------------------------------------------------
@given('the porting fixture "{name}"')
def step_porting_fixture(context: Context, name: str) -> None:
context.suite_fixture = find_fixture(_get_fixtures(PORTING_FILENAME), name)
@given('the dependency fixture "{name}"')
def step_dependency_fixture(context: Context, name: str) -> None:
context.suite_fixture = find_fixture(_get_fixtures(DEPENDENCY_FILENAME), name)
@given('the API surface fixture "{name}"')
def step_api_fixture(context: Context, name: str) -> None:
context.suite_fixture = find_fixture(_get_fixtures(API_FILENAME), name)
@given('the cross-file fixture "{name}"')
def step_cross_file_fixture(context: Context, name: str) -> None:
context.suite_fixture = find_fixture(_get_fixtures(CROSS_FILE_FILENAME), name)
@given('the circular import fixture "{name}"')
def step_circular_fixture(context: Context, name: str) -> None:
context.suite_fixture = find_fixture(_get_fixtures(CIRCULAR_FILENAME), name)
# ---------------------------------------------------------------------------
# When step - run the expected rule
# ---------------------------------------------------------------------------
@when("the suite runs the expected rule")
def step_run_expected_rule(context: Context) -> None:
from suite_helpers import RULE_MAP
fixture = context.suite_fixture
if fixture is None:
msg = "No fixture loaded"
raise RuntimeError(msg)
rule_name: str = fixture["expected_rule"]
rule = RULE_MAP[rule_name]
source: str = fixture["source"]
filename: str = fixture["filename"]
context.suite_result = rule.check(source, filename)
# ---------------------------------------------------------------------------
# Then steps - verify outcomes (with data field verification: FLAW-2 fix)
# ---------------------------------------------------------------------------
@then("the suite result matches the fixture expectation")
def step_verify_result(context: Context) -> None:
fixture = context.suite_fixture
result = context.suite_result
if fixture is None or result is None:
msg = "Fixture or result not set"
raise RuntimeError(msg)
verify_fixture_result(fixture, result)
# ---------------------------------------------------------------------------
# Fixture-loading checks (FLAW-4 fix: validate schema, not just len > 0)
# ---------------------------------------------------------------------------
@then("all porting fixtures load without error")
def step_all_porting(context: Context) -> None:
fixtures = _get_fixtures(PORTING_FILENAME)
assert len(fixtures) > 0
for f in fixtures:
validate_fixture_schema(f)
@then("all dependency fixtures load without error")
def step_all_dependency(context: Context) -> None:
fixtures = _get_fixtures(DEPENDENCY_FILENAME)
assert len(fixtures) > 0
for f in fixtures:
validate_fixture_schema(f)
@then("all API surface fixtures load without error")
def step_all_api(context: Context) -> None:
fixtures = _get_fixtures(API_FILENAME)
assert len(fixtures) > 0
for f in fixtures:
validate_fixture_schema(f)
@then("all cross-file fixtures load without error")
def step_all_cross_file(context: Context) -> None:
fixtures = _get_fixtures(CROSS_FILE_FILENAME)
assert len(fixtures) > 0
for f in fixtures:
validate_fixture_schema(f)
@then("all circular import fixtures load without error")
def step_all_circular(context: Context) -> None:
fixtures = _get_fixtures(CIRCULAR_FILENAME)
assert len(fixtures) > 0
for f in fixtures:
validate_fixture_schema(f)