build(features/steps): fix 14 files to match new ruff format
CI / lint (pull_request) Failing after 16s
CI / typecheck (pull_request) Successful in 27s
CI / coverage (pull_request) Has been skipped
CI / security (pull_request) Successful in 19s
CI / quality (pull_request) Failing after 15s
CI / behave (3.11) (pull_request) Failing after 11s
CI / behave (3.12) (pull_request) Failing after 10s
CI / behave (3.13) (pull_request) Failing after 14s
CI / docker (pull_request) Has been skipped
CI / helm (pull_request) Has been skipped
CI / build (pull_request) Failing after 13s

This commit is contained in:
2026-02-12 02:26:03 +00:00
parent 16794e43ae
commit c5004ae918
14 changed files with 219 additions and 219 deletions
+6 -6
View File
@@ -26,9 +26,9 @@ def step_check_adr_files(context):
@then("I should find at least {count:d} ADR files")
def step_verify_adr_count(context, count):
"""Verify minimum number of ADR files."""
assert (
len(context.adr_files) >= count
), f"Expected at least {count} ADR files, found {len(context.adr_files)}"
assert len(context.adr_files) >= count, (
f"Expected at least {count} ADR files, found {len(context.adr_files)}"
)
@then("each ADR should have a valid format with status")
@@ -40,9 +40,9 @@ def step_verify_adr_format(context):
assert "## Status" in content, f"{adr_file.name} missing Status section"
assert "## Context" in content, f"{adr_file.name} missing Context section"
assert "## Decision" in content, f"{adr_file.name} missing Decision section"
assert (
"## Consequences" in content
), f"{adr_file.name} missing Consequences section"
assert "## Consequences" in content, (
f"{adr_file.name} missing Consequences section"
)
@given('the source directory exists at "{path}"')
@@ -202,9 +202,9 @@ def step_assert_attempts(context, count):
@then('a CleverAgentsError should be raised with message "{message}"')
def step_assert_cleveragents_error(context, message):
exception = _get_recorded_exception(context)
assert (
exception is not None
), "Expected CleverAgentsError but no exception was recorded"
assert exception is not None, (
"Expected CleverAgentsError but no exception was recorded"
)
assert isinstance(exception, CleverAgentsError)
assert message in str(exception)
@@ -307,9 +307,9 @@ def step_assert_exit_code(context, code):
actual = _capture_exit_code(context)
if actual != code:
output = _capture_output(context)
assert (
actual == code
), f"Expected exit code {code}, got {actual}. CLI output:\n{output}"
assert actual == code, (
f"Expected exit code {code}, got {actual}. CLI output:\n{output}"
)
@then("the command should be aborted")
@@ -375,9 +375,9 @@ def step_file_in_context(context):
@then('I should see "{text}" in the output')
def step_see_text_in_output(context, text):
"""Verify text appears in command output."""
assert (
text in context.command_output
), f"Expected '{text}' in output: {context.command_output}"
assert text in context.command_output, (
f"Expected '{text}' in output: {context.command_output}"
)
@then("a new plan should be created")
@@ -517,9 +517,9 @@ def step_error_mentions(context, text):
"""Verify error message contains text."""
# Check both stdout and stderr for error messages
combined_output = (context.command_output or "") + (context.command_error or "")
assert (
text.lower() in combined_output.lower()
), f"Expected '{text}' not found in: {combined_output}"
assert text.lower() in combined_output.lower(), (
f"Expected '{text}' not found in: {combined_output}"
)
@then('the output should mention "{text}"')
+21 -21
View File
@@ -418,9 +418,9 @@ def step_check_final_content(context: Context) -> None:
@then("{count:d} changes should be marked as applied")
def step_check_applied_count(context: Context, count: int) -> None:
assert (
context.edge_applied_count == count
), f"Expected {count} applied, got {context.edge_applied_count}"
assert context.edge_applied_count == count, (
f"Expected {count} applied, got {context.edge_applied_count}"
)
@given("the plan has a CREATE change with None content")
@@ -626,13 +626,13 @@ def step_add_move_traversal_new_path(context: Context) -> None:
@then("a PlanError should be raised mentioning path traversal")
def step_check_path_traversal_error(context: Context) -> None:
assert context.edge_exception is not None, "Expected a PlanError"
assert isinstance(
context.edge_exception, PlanError
), f"Expected PlanError, got {type(context.edge_exception).__name__}"
assert isinstance(context.edge_exception, PlanError), (
f"Expected PlanError, got {type(context.edge_exception).__name__}"
)
msg = str(context.edge_exception.message).lower()
assert (
"path traversal" in msg
), f"Expected 'path traversal' in error message, got: {context.edge_exception.message}"
assert "path traversal" in msg, (
f"Expected 'path traversal' in error message, got: {context.edge_exception.message}"
)
# ──────────────────────────────────────────────────
@@ -850,9 +850,9 @@ def step_check_second_file_unchanged(context: Context) -> None:
with contextlib.suppress(Exception):
os.chmod(readonly, 0o644)
content = readonly.read_text()
assert (
content == "# original fail target content"
), f"Expected original content, got: {content}"
assert content == "# original fail target content", (
f"Expected original content, got: {content}"
)
@then("the plan cannot be restarted from errored state")
@@ -868,9 +868,9 @@ def step_plan_cannot_restart_errored(context: Context) -> None:
@then('the plan phase should remain "{expected_phase}"')
def step_plan_phase_remains(context: Context, expected_phase: str) -> None:
assert (
context.plan.phase.value == expected_phase
), f"Expected phase '{expected_phase}', got '{context.plan.phase.value}'"
assert context.plan.phase.value == expected_phase, (
f"Expected phase '{expected_phase}', got '{context.plan.phase.value}'"
)
@when("I try to execute the errored plan")
@@ -884,9 +884,9 @@ def step_try_execute_errored(context: Context) -> None:
@then("a plan not ready error should be raised for the errored plan")
def step_check_errored_exec_error(context: Context) -> None:
assert (
context.errored_exec_error is not None
), "Expected PlanNotReadyError for errored plan"
assert context.errored_exec_error is not None, (
"Expected PlanNotReadyError for errored plan"
)
assert isinstance(context.errored_exec_error, PlanNotReadyError)
@@ -901,7 +901,7 @@ def step_try_complete_strategize_after_failure(context: Context) -> None:
@then("a plan error should be raised because plan is not processing")
def step_check_post_fail_complete_error(context: Context) -> None:
assert (
context.post_fail_complete_error is not None
), "Expected PlanError when completing after failure"
assert context.post_fail_complete_error is not None, (
"Expected PlanError when completing after failure"
)
assert isinstance(context.post_fail_complete_error, PlanError)
+24 -24
View File
@@ -180,9 +180,9 @@ def step_convert_model_provider_to_string(context, member):
@then("it should be a string type")
def step_verify_string_type(context):
"""Verify the value is a string."""
assert isinstance(
context.string_value, str
), f"Not a string: {type(context.string_value)}"
assert isinstance(context.string_value, str), (
f"Not a string: {type(context.string_value)}"
)
@then('it should equal "{expected}"')
@@ -240,18 +240,18 @@ def step_iterate_enum_values(context, enum_name):
@then("I should get {count:d} enum members")
def step_verify_enum_count(context, count):
"""Verify the number of enum members."""
assert (
context.member_count == count
), f"Expected {count} members, got {context.member_count}"
assert context.member_count == count, (
f"Expected {count} members, got {context.member_count}"
)
@then("each member should be a {enum_name} instance")
def step_verify_enum_instances(context, enum_name):
"""Verify each member is an instance of the enum."""
for member in context.enum_members:
assert isinstance(
member, context.current_enum
), f"{member} is not a {enum_name} instance"
assert isinstance(member, context.current_enum), (
f"{member} is not a {enum_name} instance"
)
# Enum comparison tests
@@ -296,9 +296,9 @@ def step_access_enum_name(context, member):
@then('the name should be "{expected}"')
def step_verify_enum_name(context, expected):
"""Verify the enum name attribute."""
assert (
context.enum_name == expected
), f"Expected name {expected}, got {context.enum_name}"
assert context.enum_name == expected, (
f"Expected name {expected}, got {context.enum_name}"
)
@when("I access the value attribute of ModelPublisher.{member}")
@@ -311,9 +311,9 @@ def step_access_enum_value(context, member):
@then('the value should be "{expected}"')
def step_verify_enum_value_attr(context, expected):
"""Verify the enum value attribute."""
assert (
context.enum_value_attr == expected
), f"Expected value {expected}, got {context.enum_value_attr}"
assert context.enum_value_attr == expected, (
f"Expected value {expected}, got {context.enum_value_attr}"
)
# Creating enum from value
@@ -334,9 +334,9 @@ def step_verify_created_enum(context, member):
"""Verify the created enum member."""
expected = getattr(ModelProvider, member)
assert context.creation_successful, "Enum creation failed"
assert (
context.created_enum == expected
), f"Expected {expected}, got {context.created_enum}"
assert context.created_enum == expected, (
f"Expected {expected}, got {context.created_enum}"
)
assert context.created_enum is expected, "Enum instances should be identical"
@@ -395,15 +395,15 @@ def step_get_string_representation(context):
@then('repr should contain "{expected}"')
def step_verify_repr_contains(context, expected):
"""Verify repr contains expected string."""
assert (
expected in context.repr_value
), f"'{expected}' not in repr: {context.repr_value}"
assert expected in context.repr_value, (
f"'{expected}' not in repr: {context.repr_value}"
)
@then('str should equal "{expected}"')
def step_verify_str_equals(context, expected):
"""Verify str equals expected."""
# For str, Enum classes, str() returns the value, not the name
assert (
context.enum_value.value == expected
), f"Expected str '{expected}', got '{context.enum_value.value}'"
assert context.enum_value.value == expected, (
f"Expected str '{expected}', got '{context.enum_value.value}'"
)
+6 -6
View File
@@ -160,9 +160,9 @@ def step_assert_google_kwargs(context, kwargs_string):
expected = _parse_kwargs_string(kwargs_string)
for key, value in expected.items():
assert key in call_kwargs, f"Expected {key} in ChatGoogleGenerativeAI kwargs"
assert (
call_kwargs[key] == value
), f"Expected ChatGoogleGenerativeAI kwargs[{key!r}] to equal {value!r}"
assert call_kwargs[key] == value, (
f"Expected ChatGoogleGenerativeAI kwargs[{key!r}] to equal {value!r}"
)
@then(
@@ -184,9 +184,9 @@ def step_assert_google_metadata(context, expected_name, expected_model):
def step_assert_google_generated_change(context, count, file_path):
response = getattr(context, "response", None)
assert response is not None, "Provider response should exist"
assert (
len(response.changes) == count
), f"Expected {count} changes, got {len(response.changes)}"
assert len(response.changes) == count, (
f"Expected {count} changes, got {len(response.changes)}"
)
assert any(
getattr(change, "file_path", None) == file_path for change in response.changes
), f"Expected change for {file_path}"
+15 -15
View File
@@ -643,9 +643,9 @@ def step_assert_response_contains_validation_error(context):
assert context.response is not None
assert context.response.changes, "Expected generated changes to be returned"
assert context.response.changes[0].file_path == context.expected_change.file_path
assert (
context.response.error_message == context.expected_validation_message
), "Validation failure message should be surfaced"
assert context.response.error_message == context.expected_validation_message, (
"Validation failure message should be surfaced"
)
assert context.response.model_used == "test-model"
assert context.response.token_count == 0
assert context.requested_models == ["test-model"]
@@ -804,23 +804,23 @@ def step_assert_graph_failure_response(context):
@then("the provider response should capture the nested retry failure")
def step_assert_nested_retry_failure(context):
assert context.response is not None, "Expected provider response to be populated"
assert (
context.response.changes == []
), f"Expected no changes for nested failure, got {context.response.changes!r}"
assert (
context.response.error_message == context.failure_message
), f"Expected error message {context.failure_message!r}, got {context.response.error_message!r}"
assert context.response.changes == [], (
f"Expected no changes for nested failure, got {context.response.changes!r}"
)
assert context.response.error_message == context.failure_message, (
f"Expected error message {context.failure_message!r}, got {context.response.error_message!r}"
)
@then("the progress callback should end at 100 percent even on failure")
def step_assert_failure_progress_updates(context):
assert context.progress_updates, "Expected progress updates to be recorded"
assert (
context.progress_updates[0] == 5
), f"Expected first progress update to be 5, got {context.progress_updates[0]!r}"
assert (
context.progress_updates[-1] == 100
), f"Expected final progress update to be 100, got {context.progress_updates[-1]!r}"
assert context.progress_updates[0] == 5, (
f"Expected first progress update to be 5, got {context.progress_updates[0]!r}"
)
assert context.progress_updates[-1] == 100, (
f"Expected final progress update to be 100, got {context.progress_updates[-1]!r}"
)
@then("the stream API should preserve non-dict payloads in events")
+9 -9
View File
@@ -234,9 +234,9 @@ def step_assert_chat_openai_constructor(context, api_key, model_id):
assert call_kwargs["api_key"] == api_key
assert call_kwargs["model"] == model_id
assert (
context.plan_generation_graph_call is not None
), "PlanGenerationGraph should receive the ChatOpenAI instance"
assert context.plan_generation_graph_call is not None, (
"PlanGenerationGraph should receive the ChatOpenAI instance"
)
_, graph_kwargs = context.plan_generation_graph_call
assert graph_kwargs["llm"] is context.chat_openai_instance
@@ -262,9 +262,9 @@ def step_assert_chat_openai_kwargs(context, kwargs_string):
expected_kwargs = _parse_kwargs_string(kwargs_string)
for key, value in expected_kwargs.items():
assert key in call_kwargs, f"Expected {key} in ChatOpenAI kwargs"
assert (
call_kwargs[key] == value
), f"Expected ChatOpenAI kwargs[{key!r}] to equal {value!r}"
assert call_kwargs[key] == value, (
f"Expected ChatOpenAI kwargs[{key!r}] to equal {value!r}"
)
@then(
@@ -298,9 +298,9 @@ def step_assert_no_changes(context):
)
def step_assert_generated_change(context, count, file_path):
assert context.response is not None, "Provider response should exist"
assert (
len(context.response.changes) == count
), f"Expected {count} changes, got {len(context.response.changes)}"
assert len(context.response.changes) == count, (
f"Expected {count} changes, got {len(context.response.changes)}"
)
assert any(
getattr(change, "file_path", None) == file_path
for change in context.response.changes
+9 -9
View File
@@ -210,9 +210,9 @@ def step_assert_openrouter_kwargs(context, kwargs_string):
expected = _parse_kwargs_string(kwargs_string)
for key, value in expected.items():
assert key in call_kwargs, f"Expected {key} in ChatOpenAI kwargs"
assert (
call_kwargs[key] == value
), f"Expected ChatOpenAI kwargs[{key!r}] to equal {value!r}"
assert call_kwargs[key] == value, (
f"Expected ChatOpenAI kwargs[{key!r}] to equal {value!r}"
)
@then(
@@ -224,9 +224,9 @@ def step_assert_openrouter_headers(context, headers_string):
_, call_kwargs = call
expected = _parse_headers_string(headers_string)
actual_headers = call_kwargs.get("default_headers")
assert (
actual_headers == expected
), f"Expected default_headers {expected!r}, got {actual_headers!r}"
assert actual_headers == expected, (
f"Expected default_headers {expected!r}, got {actual_headers!r}"
)
@then(
@@ -235,9 +235,9 @@ def step_assert_openrouter_headers(context, headers_string):
def step_assert_openrouter_generated_change(context, count, file_path):
response = getattr(context, "response", None)
assert response is not None, "Provider response should exist"
assert (
len(response.changes) == count
), f"Expected {count} changes, got {len(response.changes)}"
assert len(response.changes) == count, (
f"Expected {count} changes, got {len(response.changes)}"
)
assert any(
getattr(change, "file_path", None) == file_path for change in response.changes
), f"Expected change for {file_path}"
+9 -9
View File
@@ -1128,9 +1128,9 @@ def step_assert_typer_abort(context):
@then("the plan tell should execute successfully")
def step_plan_tell_success(context):
"""Assert plan tell executed successfully."""
assert (
context.result.exit_code == 0
), f"Exit code was {context.result.exit_code}, output: {context.result.output}"
assert context.result.exit_code == 0, (
f"Exit code was {context.result.exit_code}, output: {context.result.output}"
)
assert "Plan created" in context.result.output or "" in context.result.output
@@ -1176,12 +1176,12 @@ def step_plan_tell_general_abort(context):
@then("the plan tell streaming path should execute successfully")
def step_plan_tell_streaming_success(context):
"""Assert plan tell streaming path executed via asyncio."""
assert (
context.result.exit_code == 0
), f"Exit code was {context.result.exit_code}, output: {context.result.output}"
assert (
getattr(context, "stream_call_count", 0) == 1
), "Streaming coroutine was not awaited"
assert context.result.exit_code == 0, (
f"Exit code was {context.result.exit_code}, output: {context.result.output}"
)
assert getattr(context, "stream_call_count", 0) == 1, (
"Streaming coroutine was not awaited"
)
assert context.stream_call_args, "No streaming call arguments recorded"
first_call = context.stream_call_args[0]
assert first_call.args[1] == context.stream_prompt
+48 -48
View File
@@ -1046,9 +1046,9 @@ def step_assert_lazy_registry_actor(
registry = getattr(context, "lazy_registry", None)
assert registry is not None, "Lazy registry stub was not configured"
expected = {"provider": provider.lower(), "model": model.lower()}
assert registry.requests == [
expected
], "Lazy registry did not capture the actor request"
assert registry.requests == [expected], (
"Lazy registry did not capture the actor request"
)
resolution = getattr(context, "provider_resolution", None)
assert resolution is not None, "Provider resolution result missing"
@@ -1314,9 +1314,9 @@ def step_assert_stream_token_count(context: Context, expected: int) -> None:
with context.unit_of_work.transaction() as ctx:
plan = ctx.plans.get_current_for_project(context.test_project.id)
assert plan is not None, "Plan was not persisted"
assert (
plan.token_count == expected
), f"Expected token count {expected}, got {plan.token_count}"
assert plan.token_count == expected, (
f"Expected token count {expected}, got {plan.token_count}"
)
@then('the streaming failure events should include an error with message "{message}"')
@@ -1333,9 +1333,9 @@ def step_assert_stream_failure_event(context: Context, message: str) -> None:
failure_payload = payload
break
assert failure_payload is not None, "Expected a failure event in the stream"
assert (
failure_payload.get("error") == message
), f"Expected failure message '{message}', got '{failure_payload.get('error')}'"
assert failure_payload.get("error") == message, (
f"Expected failure message '{message}', got '{failure_payload.get('error')}'"
)
@then(
@@ -1347,9 +1347,9 @@ def step_assert_non_python_stream(context: Context) -> None:
events = getattr(context, "stream_events", [])
assert events, "Streaming events were not captured"
end_event = events[-1]
assert (
isinstance(end_event, dict) and "__end__" in end_event
), "Final streaming event did not include end payload"
assert isinstance(end_event, dict) and "__end__" in end_event, (
"Final streaming event did not include end payload"
)
payload = end_event["__end__"]
changes = payload.get("changes") or []
assert len(changes) == 1, "Expected exactly one streamed change"
@@ -1395,12 +1395,12 @@ def step_assert_stub_provider_requests(
requests = getattr(context, "stub_provider_requests", None)
assert requests, "No provider override requests were recorded"
last_request = requests[-1]
assert (
last_request["provider"] == provider
), f"Expected provider '{provider}', got '{last_request['provider']}'"
assert (
last_request["model"] == model
), f"Expected model '{model}', got '{last_request['model']}'"
assert last_request["provider"] == provider, (
f"Expected provider '{provider}', got '{last_request['provider']}'"
)
assert last_request["model"] == model, (
f"Expected model '{model}', got '{last_request['model']}'"
)
@given("I have a plan service without providers configured")
@@ -1546,9 +1546,9 @@ def step_assert_validation_hint(context: Context) -> None:
@given('the project has plans named "{first}" and "{second}"')
def step_project_with_named_plans(context: Context, first: str, second: str) -> None:
"""Ensure the project has specific plan names configured."""
assert (
context.project.id is not None
), "Project must be persisted before adding plans"
assert context.project.id is not None, (
"Project must be persisted before adding plans"
)
with context.unit_of_work.transaction() as ctx:
current_plan = ctx.plans.get_current_for_project(context.project.id)
assert current_plan is not None, "Current plan is required for this step"
@@ -1718,9 +1718,9 @@ def step_try_build_plan_no_current(context: Context) -> None:
def step_check_plan_error(context: Context, message: str) -> None:
"""Check that a PlanError was raised with specific message."""
assert context.exception is not None, "No exception captured"
assert isinstance(
context.exception, PlanError
), f"Unexpected exception type {type(context.exception).__name__}"
assert isinstance(context.exception, PlanError), (
f"Unexpected exception type {type(context.exception).__name__}"
)
actual_message = str(getattr(context.exception, "message", "")) or str(
context.exception
)
@@ -1739,9 +1739,9 @@ def step_check_plan_error_contains(context: Context, message: str) -> None:
def step_plan_error_details_include_provider_diagnostics(context: Context) -> None:
"""Ensure provider diagnostics are present in the captured PlanError details."""
assert context.exception is not None, "No exception captured"
assert isinstance(
context.exception, PlanError
), f"Expected PlanError but got {type(context.exception).__name__}"
assert isinstance(context.exception, PlanError), (
f"Expected PlanError but got {type(context.exception).__name__}"
)
details = getattr(context.exception, "details", {}) or {}
required_keys = {
"configured_providers",
@@ -1756,9 +1756,9 @@ def step_plan_error_details_include_provider_diagnostics(context: Context) -> No
@given("I configured an auto-debug plan with a disappearing plan ID")
def step_configure_auto_debug_disappearing_plan(context: Context) -> None:
"""Set up a plan service whose current plan loses its ID mid-run."""
assert hasattr(
context, "temp_dir"
), "Temporary directory setup is required before configuring auto-debug"
assert hasattr(context, "temp_dir"), (
"Temporary directory setup is required before configuring auto-debug"
)
class FlickeringPlan:
def __init__(self, plan_id: int) -> None:
@@ -2306,18 +2306,18 @@ def step_check_nested_move(context: Context) -> None:
old_path, new_path = context.nested_move_paths
assert not old_path.exists(), "Original nested file still exists"
assert new_path.exists(), "Nested destination file was not created"
assert (
new_path.read_text() == "# Nested file to move"
), "Nested destination content mismatch"
assert new_path.read_text() == "# Nested file to move", (
"Nested destination content mismatch"
)
@given("the plan has a pending MOVE change to an absolute path")
def step_add_absolute_move_change(context: Context) -> None:
"""Add a MOVE change whose destination is an absolute path."""
assert getattr(context, "project", None) is not None, "Project is required"
assert (
getattr(context, "current_plan", None) is not None
), "Current plan is required"
assert getattr(context, "current_plan", None) is not None, (
"Current plan is required"
)
source_path = context.project.path / "absolute_source.py"
source_path.write_text("# Absolute move source")
@@ -2440,12 +2440,12 @@ def step_check_plan_error_with_details(context: Context) -> None:
with contextlib.suppress(builtins.BaseException):
os.chmod(context.readonly_file, 0o644)
assert (
context.exception is not None
), f"Expected an exception but got result: {getattr(context, 'apply_result', 'none')}"
assert isinstance(
context.exception, PlanError
), f"Expected PlanError but got {type(context.exception).__name__}: {context.exception}"
assert context.exception is not None, (
f"Expected an exception but got result: {getattr(context, 'apply_result', 'none')}"
)
assert isinstance(context.exception, PlanError), (
f"Expected PlanError but got {type(context.exception).__name__}: {context.exception}"
)
assert "Failed to apply change" in str(context.exception.message)
@@ -3295,9 +3295,9 @@ def step_assert_langsmith_builder_base_metadata(
assert metadata.get("project_name") == project_name
assert metadata.get("project_id") is None
extra_metadata_keys = set(metadata.keys()) - {"project_id", "project_name"}
assert (
not extra_metadata_keys
), f"Unexpected metadata keys present: {sorted(extra_metadata_keys)}"
assert not extra_metadata_keys, (
f"Unexpected metadata keys present: {sorted(extra_metadata_keys)}"
)
assert tags == ["service:plan"], f"Expected only base service tag, got {tags}"
@@ -3477,9 +3477,9 @@ def step_assert_auto_debug_retry_success(context: Context) -> None:
attempts = getattr(context, "latest_debug_attempts", []) or []
assert attempts, "No debug attempts were recorded"
assert any(
attempt.success for attempt in attempts
), "Debug attempt was not marked successful"
assert any(attempt.success for attempt in attempts), (
"Debug attempt was not marked successful"
)
@when("I try to stream plan generation without an AI provider")
@@ -673,6 +673,6 @@ def step_project_command_should_succeed(context):
@then("the project command should exit with code {code:d}")
def step_project_command_exit_code(context, code):
"""Assert the project command exited with the expected code."""
assert (
context.result.exit_code == code
), f"Expected exit code {code}, got {context.result.exit_code}. Output: {context.result.output}"
assert context.result.exit_code == code, (
f"Expected exit code {code}, got {context.result.exit_code}. Output: {context.result.output}"
)
+24 -24
View File
@@ -121,27 +121,27 @@ def step_apply_async_exponential_retry(context, max_attempts):
@then("the function should eventually succeed")
def step_verify_function_succeeded(context):
"""Verify function succeeded after retries."""
assert (
context.retry_succeeded
), f"Function failed: {getattr(context, 'retry_error', 'Unknown error')}"
assert context.retry_succeeded, (
f"Function failed: {getattr(context, 'retry_error', 'Unknown error')}"
)
assert context.result == "success"
@then("the async function should eventually succeed")
def step_verify_async_function_succeeded(context):
"""Verify async function succeeded after retries."""
assert (
context.retry_succeeded
), f"Async function failed: {getattr(context, 'retry_error', 'Unknown error')}"
assert context.retry_succeeded, (
f"Async function failed: {getattr(context, 'retry_error', 'Unknown error')}"
)
assert context.result == "async success"
@then("the function should be called {expected_calls:d} times")
def step_verify_call_count(context, expected_calls):
"""Verify function was called expected number of times."""
assert (
context.call_count == expected_calls
), f"Expected {expected_calls} calls, got {context.call_count}"
assert context.call_count == expected_calls, (
f"Expected {expected_calls} calls, got {context.call_count}"
)
# Network retry pattern tests
@@ -182,9 +182,9 @@ def step_verify_network_retry(context):
@then("the function should be called {max_calls:d} times maximum")
def step_verify_max_calls(context, max_calls):
"""Verify function wasn't called more than max times."""
assert (
context.call_count <= max_calls
), f"Function called {context.call_count} times, max is {max_calls}"
assert context.call_count <= max_calls, (
f"Function called {context.call_count} times, max is {max_calls}"
)
# Provider retry pattern tests
@@ -261,18 +261,18 @@ def step_apply_file_retry(context):
@then("the file operation should eventually succeed")
def step_verify_file_retry_success(context):
"""Verify the file operation eventually succeeds."""
assert (
context.file_retry_succeeded
), f"File retry failed: {getattr(context, 'file_retry_error', 'Unknown error')}"
assert context.file_retry_succeeded, (
f"File retry failed: {getattr(context, 'file_retry_error', 'Unknown error')}"
)
assert context.file_result == "file success"
@then("the file operation should be invoked {expected:d} times")
def step_verify_file_retry_invocations(context, expected):
"""Verify the file operation was invoked the expected number of times."""
assert (
context.file_call_count == expected
), f"Expected {expected} calls, got {context.file_call_count}"
assert context.file_call_count == expected, (
f"Expected {expected} calls, got {context.file_call_count}"
)
# Circuit breaker tests
@@ -496,9 +496,9 @@ def step_async_retry_context_manager_failure(context):
@then("the async retry context manager should capture the exception")
def step_verify_async_retry_context_manager_capture(context):
"""Ensure the async retry context manager captured the exception."""
assert (
context.async_retry_context_manager_error
), "Expected async runtime error to propagate"
assert context.async_retry_context_manager_error, (
"Expected async runtime error to propagate"
)
assert context.retry_context_errors_added_async >= 1
assert isinstance(context.retry_context.errors[-1], Exception)
@@ -690,9 +690,9 @@ def step_apply_retry_on_result(context, max_attempts):
@then("the decorated function should return the successful payload")
def step_verify_retry_on_result_payload(context):
"""Ensure retry_on_result eventually returns the non-retry payload."""
assert (
context.retry_on_result_succeeded
), f"Retry on result failed: {context.retry_on_result_output}"
assert context.retry_on_result_succeeded, (
f"Retry on result failed: {context.retry_on_result_output}"
)
assert isinstance(context.retry_on_result_output, dict)
assert context.retry_on_result_output.get("retry") is False
+33 -33
View File
@@ -49,9 +49,9 @@ def step_validate_code_ast(context: Context, code: str) -> None:
def step_check_stream_routing_error(context: Context, text: str) -> None:
assert context.ast_error is not None, "Expected StreamRoutingError"
assert isinstance(context.ast_error, StreamRoutingError)
assert text in str(
context.ast_error
), f"Expected '{text}' in error: {context.ast_error}"
assert text in str(context.ast_error), (
f"Expected '{text}' in error: {context.ast_error}"
)
@then("no error should be raised from ast validation")
@@ -159,16 +159,16 @@ def step_sanitize_fenced_content(context: Context, inner: str) -> None:
@then('the sanitized content should be "{expected}"')
def step_check_sanitized_content(context: Context, expected: str) -> None:
assert (
context.sanitized_content == expected
), f"Expected '{expected}', got '{context.sanitized_content}'"
assert context.sanitized_content == expected, (
f"Expected '{expected}', got '{context.sanitized_content}'"
)
@then("the sanitization error should be None")
def step_check_sanitized_error_none(context: Context) -> None:
assert (
context.sanitized_error is None
), f"Expected no error, got: {context.sanitized_error}"
assert context.sanitized_error is None, (
f"Expected no error, got: {context.sanitized_error}"
)
@then("the sanitization error should not be None")
@@ -178,16 +178,16 @@ def step_check_sanitized_error_not_none(context: Context) -> None:
@then("the sanitization reason should be None")
def step_check_sanitized_reason_none(context: Context) -> None:
assert (
context.sanitized_reason is None
), f"Expected no reason, got: {context.sanitized_reason}"
assert context.sanitized_reason is None, (
f"Expected no reason, got: {context.sanitized_reason}"
)
@then('the sanitization reason should be "{expected}"')
def step_check_sanitized_reason(context: Context, expected: str) -> None:
assert (
context.sanitized_reason == expected
), f"Expected reason '{expected}', got '{context.sanitized_reason}'"
assert context.sanitized_reason == expected, (
f"Expected reason '{expected}', got '{context.sanitized_reason}'"
)
# ──────────────────────────────────────────────────
@@ -216,9 +216,9 @@ def step_try_create_project_invalid_name(context: Context, name: str) -> None:
@then('a project validation error should be raised mentioning "{text}"')
def step_check_project_validation_error(context: Context, text: str) -> None:
assert context.project_error is not None, "Expected a validation error"
assert (
text.lower() in str(context.project_error).lower()
), f"Expected '{text}' in error: {context.project_error}"
assert text.lower() in str(context.project_error).lower(), (
f"Expected '{text}' in error: {context.project_error}"
)
@when('I create a project fixture with name "{name}"')
@@ -255,9 +255,9 @@ def step_create_project_relative_path(context: Context, rel_path: str) -> None:
@then("the project fixture path should be absolute")
def step_check_project_path_absolute(context: Context) -> None:
assert (
context.created_project.path.is_absolute()
), f"Expected absolute path, got: {context.created_project.path}"
assert context.created_project.path.is_absolute(), (
f"Expected absolute path, got: {context.created_project.path}"
)
@when("I try to create a project with empty name")
@@ -308,9 +308,9 @@ def step_coerce_empty_list(context: Context) -> None:
@then("the coerced result should be an empty list")
def step_check_coerced_empty(context: Context) -> None:
assert (
context.coerced_result == []
), f"Expected empty list, got: {context.coerced_result}"
assert context.coerced_result == [], (
f"Expected empty list, got: {context.coerced_result}"
)
@when("I coerce a list with one dict entry and one Change entry")
@@ -348,9 +348,9 @@ def step_coerce_mixed_list(context: Context) -> None:
@then("the coerced result should have {count:d} changes")
def step_check_coerced_count(context: Context, count: int) -> None:
assert (
len(context.coerced_result) == count
), f"Expected {count} changes, got {len(context.coerced_result)}"
assert len(context.coerced_result) == count, (
f"Expected {count} changes, got {len(context.coerced_result)}"
)
@when("I try to coerce a non-list input")
@@ -370,9 +370,9 @@ def step_coerce_non_list(context: Context) -> None:
def step_check_coerce_plan_error(context: Context, text: str) -> None:
assert context.coerce_error is not None, "Expected PlanError"
assert isinstance(context.coerce_error, PlanError)
assert text in str(
context.coerce_error.message
), f"Expected '{text}' in error: {context.coerce_error.message}"
assert text in str(context.coerce_error.message), (
f"Expected '{text}' in error: {context.coerce_error.message}"
)
@when("I try to coerce a list containing an integer")
@@ -425,7 +425,7 @@ def step_try_create_arg_with_name(context: Context, name: str) -> None:
@then("the argument name should be accepted as valid identifier")
def step_check_arg_name_accepted(context: Context) -> None:
# "class" is a valid Python identifier (keyword but still passes str.isidentifier())
assert (
context.created_arg is not None
), f"Expected argument creation to succeed, got error: {context.arg_create_error}"
assert context.created_arg is not None, (
f"Expected argument creation to succeed, got error: {context.arg_create_error}"
)
assert context.created_arg.name == "class"