test(a2a): add regression tests to verify zero acp references after module rename #10668

Merged
HAL9000 merged 6 commits from test/v3.6.0/a2a-rename-regression-tests into master 2026-06-17 01:31:27 +00:00
2 changed files with 452 additions and 0 deletions
+71
View File
@@ -0,0 +1,71 @@
Feature: A2A Module Naming Regression Tests
Verify zero ACP references remain after module rename
and ensure A2A module imports work correctly
Background:
Given the A2A module is properly installed
And no ACP references exist in the codebase
Scenario: Import A2A facade from new module path
When I import the A2A facade from "cleveragents.a2a"
Then the import succeeds
And the facade is an instance of A2aLocalFacade
Scenario: Import A2A clients from new module path
When I import A2A clients from "cleveragents.a2a"
Then the import succeeds
And the clients module contains ServerClient
Scenario: Import A2A models from new module path
When I import A2A models from "cleveragents.a2a"
Then the import succeeds
And the models module contains A2aRequest
Scenario: Import A2A errors from new module path
When I import A2A errors from "cleveragents.a2a"
Then the import succeeds
And the errors module contains A2aError
Scenario: Import A2A events from new module path
When I import A2A events from "cleveragents.a2a"
Then the import succeeds
And the events module contains A2aEventQueue
Scenario: Old ACP import path raises ImportError
When I attempt to import from old "cleveragents.acp" path
Then an ImportError is raised
And the error message indicates the module does not exist
Scenario: A2A __init__ exports all public symbols
When I import from "cleveragents.a2a"
Then the module exports A2aLocalFacade
And the module exports ServerClient
And the module exports A2aRequest
And the module exports A2aError
And the module exports A2aEventQueue
Scenario: No ACP references in source code
When I scan the source code for ACP references
Then no "acp" imports are found
And no "from cleveragents.acp" statements are found
And no "import cleveragents.acp" statements are found
Scenario: A2A module structure is complete
When I inspect the A2A module structure
Then the module contains __init__.py
And the module contains facade.py
And the module contains clients.py
And the module contains models.py
And the module contains errors.py
And the module contains events.py
And the module contains asgi.py
And the module contains transport.py
And the module contains versioning.py
And the module contains server_config.py
And the module contains cli_bootstrap.py
Scenario: A2A facade initialization works correctly
When I initialize the A2A facade
Then the facade initializes without errors
And the facade has required methods
And the facade can be used for A2A operations
@@ -0,0 +1,381 @@
"""Step definitions for A2A naming regression tests."""
import importlib
from pathlib import Path
from typing import Any
from behave import given, then, when
@given("the A2A module is properly installed")
def step_a2a_module_installed(context: Any) -> None:
"""Verify the A2A module is properly installed."""
try:
import cleveragents.a2a # noqa: F401
context.a2a_module = importlib.import_module("cleveragents.a2a")
except ImportError as e:
raise AssertionError(f"A2A module not installed: {e}") from e
@given("no ACP references exist in the codebase")
def step_no_acp_references(context: Any) -> None:
"""Verify no ACP references exist in the codebase."""
# This is verified by the linting step, but we can check here too
src_path = Path(__file__).parent.parent.parent / "src"
acp_found = False
for py_file in src_path.rglob("*.py"):
with open(py_file, encoding="utf-8") as f:
content = f.read()
if "acp" in content.lower():
# Check if it's actually an ACP reference (not just in comments)
for line in content.split("\n"):
if (
"acp" in line.lower()
and not line.strip().startswith("#")
and (
"from cleveragents.acp" in line
or "import cleveragents.acp" in line
)
):
acp_found = True
break
if acp_found:
raise AssertionError("ACP references found in source code")
@when('I import the A2A facade from "cleveragents.a2a"')
def step_import_a2a_facade(context: Any) -> None:
"""Import the A2A facade from the new module path."""
try:
from cleveragents.a2a import A2aLocalFacade
context.a2a_facade = A2aLocalFacade
except ImportError as e:
raise AssertionError(f"Failed to import A2A facade: {e}") from e
@then("the import succeeds")
def step_import_succeeds(context: Any) -> None:
"""Verify the import succeeded."""
assert (
hasattr(context, "a2a_facade")
or hasattr(context, "a2a_clients")
or hasattr(context, "a2a_models")
or hasattr(context, "a2a_errors")
or hasattr(context, "a2a_events")
), "Import did not succeed"
@then("the facade is an instance of A2aLocalFacade")
def step_facade_is_a2a_facade(context: Any) -> None:
"""Verify the facade is an instance of A2aLocalFacade."""
from cleveragents.a2a import A2aLocalFacade
assert context.a2a_facade is A2aLocalFacade, "Facade is not A2aLocalFacade"
@when('I import A2A clients from "cleveragents.a2a"')
def step_import_a2a_clients(context: Any) -> None:
"""Import A2A clients from the new module path."""
try:
from cleveragents.a2a import ServerClient
context.a2a_clients = ServerClient
except ImportError as e:
raise AssertionError(f"Failed to import A2A clients: {e}") from e
@then("the clients module contains ServerClient")
def step_clients_contains_factory(context: Any) -> None:
"""Verify the clients module contains ServerClient."""
from cleveragents.a2a import ServerClient
assert ServerClient is not None, "ServerClient not found in clients module"
@when('I import A2A models from "cleveragents.a2a"')
def step_import_a2a_models(context: Any) -> None:
"""Import A2A models from the new module path."""
try:
from cleveragents.a2a import A2aRequest
context.a2a_models = A2aRequest
except ImportError as e:
raise AssertionError(f"Failed to import A2A models: {e}") from e
@then("the models module contains A2aRequest")
def step_models_contains_message(context: Any) -> None:
"""Verify the models module contains A2aRequest."""
from cleveragents.a2a import A2aRequest
assert A2aRequest is not None, "A2aRequest not found in models module"
@when('I import A2A errors from "cleveragents.a2a"')
def step_import_a2a_errors(context: Any) -> None:
"""Import A2A errors from the new module path."""
try:
from cleveragents.a2a import A2aError
context.a2a_errors = A2aError
except ImportError as e:
raise AssertionError(f"Failed to import A2A errors: {e}") from e
@then("the errors module contains A2aError")
def step_errors_contains_error(context: Any) -> None:
"""Verify the errors module contains A2aError."""
from cleveragents.a2a import A2aError
assert A2aError is not None, "A2aError not found in errors module"
@when('I import A2A events from "cleveragents.a2a"')
def step_import_a2a_events(context: Any) -> None:
"""Import A2A events from the new module path."""
try:
from cleveragents.a2a import A2aEventQueue
context.a2a_events = A2aEventQueue
except ImportError as e:
raise AssertionError(f"Failed to import A2A events: {e}") from e
@then("the events module contains A2aEventQueue")
def step_events_contains_emitter(context: Any) -> None:
"""Verify the events module contains A2aEventQueue."""
from cleveragents.a2a import A2aEventQueue
assert A2aEventQueue is not None, "A2aEventQueue not found in events module"
@when('I attempt to import from old "cleveragents.acp" path')
def step_attempt_import_acp(context: Any) -> None:
"""Attempt to import from the old ACP path."""
context.import_error = None
try:
importlib.import_module("cleveragents.acp")
except ImportError as e:
context.import_error = e
@then("an ImportError is raised")
def step_import_error_raised(context: Any) -> None:
"""Verify an ImportError was raised."""
assert context.import_error is not None, "ImportError was not raised"
@then("the error message indicates the module does not exist")
def step_error_message_correct(context: Any) -> None:
"""Verify the error message indicates the module does not exist."""
error_msg = str(context.import_error).lower()
assert (
"no module" in error_msg or "cannot find" in error_msg or "acp" in error_msg
), f"Error message does not indicate missing module: {context.import_error}"
@when('I import from "cleveragents.a2a"')
def step_import_from_a2a(context: Any) -> None:
"""Import from the A2A module."""
try:
context.a2a_module = importlib.import_module("cleveragents.a2a")
except ImportError as e:
raise AssertionError(f"Failed to import from cleveragents.a2a: {e}") from e
@then("the module exports A2aLocalFacade")
def step_module_exports_facade(context: Any) -> None:
"""Verify the module exports A2aLocalFacade."""
assert hasattr(context.a2a_module, "A2aLocalFacade"), (
"A2aLocalFacade not exported from cleveragents.a2a"
)
@then("the module exports ServerClient")
def step_module_exports_factory(context: Any) -> None:
"""Verify the module exports ServerClient."""
assert hasattr(context.a2a_module, "ServerClient"), (
"ServerClient not exported from cleveragents.a2a"
)
@then("the module exports A2aRequest")
def step_module_exports_message(context: Any) -> None:
"""Verify the module exports A2aRequest."""
assert hasattr(context.a2a_module, "A2aRequest"), (
"A2aRequest not exported from cleveragents.a2a"
)
@then("the module exports A2aError")
def step_module_exports_error(context: Any) -> None:
"""Verify the module exports A2aError."""
assert hasattr(context.a2a_module, "A2aError"), (
"A2aError not exported from cleveragents.a2a"
)
@then("the module exports A2aEventQueue")
def step_module_exports_emitter(context: Any) -> None:
"""Verify the module exports A2aEventQueue."""
assert hasattr(context.a2a_module, "A2aEventQueue"), (
"A2aEventQueue not exported from cleveragents.a2a"
)
@when("I scan the source code for ACP references")
def step_scan_acp_references(context: Any) -> None:
"""Scan the source code for ACP references."""
src_path = Path(__file__).parent.parent.parent / "src"
context.acp_imports = []
context.acp_from_imports = []
context.acp_import_statements = []
for py_file in src_path.rglob("*.py"):
with open(py_file, encoding="utf-8") as f:
for line_num, line in enumerate(f, 1):
if line.strip().startswith("#"):
continue
if "from cleveragents.acp" in line:
context.acp_from_imports.append((py_file, line_num, line.strip()))
if "import cleveragents.acp" in line:
context.acp_import_statements.append(
(py_file, line_num, line.strip())
)
if " acp " in line.lower() and "a2a" not in line.lower():
context.acp_imports.append((py_file, line_num, line.strip()))
@then('no "acp" imports are found')
def step_no_acp_imports(context: Any) -> None:
"""Verify no ACP imports are found."""
assert len(context.acp_imports) == 0, f"ACP imports found: {context.acp_imports}"
@then('no "from cleveragents.acp" statements are found')
def step_no_from_acp_statements(context: Any) -> None:
"""Verify no 'from cleveragents.acp' statements are found."""
assert len(context.acp_from_imports) == 0, (
f"'from cleveragents.acp' statements found: {context.acp_from_imports}"
)
@then('no "import cleveragents.acp" statements are found')
def step_no_import_acp_statements(context: Any) -> None:
"""Verify no 'import cleveragents.acp' statements are found."""
assert len(context.acp_import_statements) == 0, (
f"'import cleveragents.acp' statements found: {context.acp_import_statements}"
)
@when("I inspect the A2A module structure")
def step_inspect_a2a_structure(context: Any) -> None:
"""Inspect the A2A module structure."""
a2a_path = Path(__file__).parent.parent.parent / "src" / "cleveragents" / "a2a"
context.a2a_files = set(f.name for f in a2a_path.glob("*.py"))
@then("the module contains __init__.py")
def step_module_contains_init(context: Any) -> None:
"""Verify the module contains __init__.py."""
assert "__init__.py" in context.a2a_files, "__init__.py not found"
@then("the module contains facade.py")
def step_module_contains_facade(context: Any) -> None:
"""Verify the module contains facade.py."""
assert "facade.py" in context.a2a_files, "facade.py not found"
@then("the module contains clients.py")
def step_module_contains_clients(context: Any) -> None:
"""Verify the module contains clients.py."""
assert "clients.py" in context.a2a_files, "clients.py not found"
@then("the module contains models.py")
def step_module_contains_models(context: Any) -> None:
"""Verify the module contains models.py."""
assert "models.py" in context.a2a_files, "models.py not found"
@then("the module contains errors.py")
def step_module_contains_errors(context: Any) -> None:
"""Verify the module contains errors.py."""
assert "errors.py" in context.a2a_files, "errors.py not found"
@then("the module contains events.py")
def step_module_contains_events(context: Any) -> None:
"""Verify the module contains events.py."""
assert "events.py" in context.a2a_files, "events.py not found"
@then("the module contains asgi.py")
def step_module_contains_asgi(context: Any) -> None:
"""Verify the module contains asgi.py."""
assert "asgi.py" in context.a2a_files, "asgi.py not found"
@then("the module contains transport.py")
def step_module_contains_transport(context: Any) -> None:
"""Verify the module contains transport.py."""
assert "transport.py" in context.a2a_files, "transport.py not found"
@then("the module contains versioning.py")
def step_module_contains_versioning(context: Any) -> None:
"""Verify the module contains versioning.py."""
assert "versioning.py" in context.a2a_files, "versioning.py not found"
@then("the module contains server_config.py")
def step_module_contains_server_config(context: Any) -> None:
"""Verify the module contains server_config.py."""
assert "server_config.py" in context.a2a_files, "server_config.py not found"
@then("the module contains cli_bootstrap.py")
def step_module_contains_cli_bootstrap(context: Any) -> None:
"""Verify the module contains cli_bootstrap.py."""
assert "cli_bootstrap.py" in context.a2a_files, "cli_bootstrap.py not found"
@when("I initialize the A2A facade")
def step_initialize_a2a_facade(context: Any) -> None:
"""Initialize the A2A facade."""
try:
from cleveragents.a2a import A2aLocalFacade
context.facade_instance = A2aLocalFacade()
except Exception as e:
context.facade_init_error = e
@then("the facade initializes without errors")
def step_facade_initializes(context: Any) -> None:
"""Verify the facade initializes without errors."""
assert not hasattr(context, "facade_init_error"), (
f"Facade initialization failed: {getattr(context, 'facade_init_error', None)}"
)
assert hasattr(context, "facade_instance"), "Facade instance not created"
@then("the facade has required methods")
def step_facade_has_methods(context: Any) -> None:
"""Verify the facade has required methods."""
facade = context.facade_instance
# Check for common facade methods
assert callable(getattr(facade, "__init__", None)), "Facade missing __init__"
@then("the facade can be used for A2A operations")
def step_facade_usable(context: Any) -> None:
"""Verify the facade can be used for A2A operations."""
facade = context.facade_instance
assert facade is not None, "Facade is None"
assert hasattr(facade, "__class__"), "Facade has no class"