Files
temp/tests/features/steps/route_missing_coverage_steps.py
T

408 lines
15 KiB
Python

"""
BDD step definitions for specific missing coverage lines in route.py.
"""
from pathlib import Path
from behave import given, then, when
from behave.runner import Context
from cleveragents.langgraph.graph import GraphConfig
from cleveragents.langgraph.nodes import Edge, NodeConfig, NodeType
from cleveragents.reactive.route import RouteComplexityAnalyzer, RouteConfig, RouteType
from cleveragents.reactive.stream_router import StreamConfig, StreamType
@given("I have a StreamConfig with all optional properties set")
def step_create_stream_config_all_properties(context: Context):
"""Create a StreamConfig with all optional properties."""
context.full_stream_config = StreamConfig(
name="full_stream",
type=StreamType.HOT,
operators=[
{"type": "map", "params": {"transform": "data"}},
{"type": "filter", "params": {"condition": "valid"}},
],
subscriptions=["input1", "input2"],
publications=["output1", "output2"],
agents=["agent1", "agent2"],
initial_value={"start": "value"},
buffer_size=20,
template_config={"template": "advanced", "vars": {"key": "value"}},
)
@when("I call RouteConfig.from_stream_config directly")
def step_call_from_stream_config_directly(context: Context):
"""Call RouteConfig.from_stream_config directly."""
context.result_route = RouteConfig.from_stream_config(context.full_stream_config)
@then("line 170 should be executed")
def step_line_170_executed(context: Context):
"""Verify line 170 is executed (return cls(...))."""
# This is verified by the successful creation
assert context.result_route is not None
assert isinstance(context.result_route, RouteConfig)
@then("all stream properties should be copied correctly")
def step_all_stream_properties_copied(context: Context):
"""Verify all stream properties are copied correctly."""
route = context.result_route
source = context.full_stream_config
assert route.name == source.name
assert route.type == RouteType.STREAM
assert route.stream_type == source.type
assert route.operators == source.operators
assert route.subscriptions == source.subscriptions
assert route.publications == source.publications
assert route.agents == source.agents
assert route.initial_value == source.initial_value
assert route.buffer_size == source.buffer_size
assert route.template_config == source.template_config
@given("I have a GraphConfig with nodes having all optional properties")
def step_create_graph_config_all_properties(context: Context):
"""Create a GraphConfig with nodes having all optional properties."""
# Create nodes with all possible properties
agent_node = NodeConfig(
name="agent_node",
type=NodeType.AGENT,
agent="test_agent",
tools=["tool1", "tool2", "tool3"],
retry_policy={"max_retries": 5, "backoff": "exponential"},
timeout=60,
parallel=True,
metadata={"category": "processing"},
)
function_node = NodeConfig(
name="function_node",
type=NodeType.FUNCTION,
function="process_data",
tools=["utility_tool"],
retry_policy={"max_retries": 3},
timeout=30,
parallel=False,
condition="data_valid",
subgraph="sub_process",
)
start_node = NodeConfig(name="start_node", type=NodeType.START, parallel=False)
# Create edges with conditions
edge_with_condition = Edge(
source="start_node",
target="agent_node",
condition="input_ready",
metadata={"priority": "high"},
)
edge_without_condition = Edge(source="agent_node", target="function_node")
context.full_graph_config = GraphConfig(
name="full_graph",
nodes={
"agent_node": agent_node,
"function_node": function_node,
"start_node": start_node,
},
edges=[edge_with_condition, edge_without_condition],
entry_point="start_node",
state_class=None,
checkpointing=True,
checkpoint_dir=Path("/tmp/test_checkpoints"),
enable_time_travel=True,
parallel_execution=True,
metadata={"version": "1.0", "author": "test"},
)
@when("I call RouteConfig.from_graph_config directly")
def step_call_from_graph_config_directly(context: Context):
"""Call RouteConfig.from_graph_config directly."""
context.result_route = RouteConfig.from_graph_config(context.full_graph_config)
@then("lines 187-216 should be executed")
def step_lines_187_216_executed(context: Context):
"""Verify lines 187-216 are executed."""
# This is verified by successful conversion with all properties
assert context.result_route is not None
assert context.result_route.type == RouteType.GRAPH
assert len(context.result_route.nodes) == 3
assert len(context.result_route.edges) == 2
@then("nodes with tools should be converted")
def step_nodes_with_tools_converted(context: Context):
"""Verify nodes with tools are converted (lines 197-198)."""
route = context.result_route
# Check agent_node has tools
agent_node = route.nodes["agent_node"]
assert "tools" in agent_node
assert agent_node["tools"] == ["tool1", "tool2", "tool3"]
# Check function_node has tools
function_node = route.nodes["function_node"]
assert "tools" in function_node
assert function_node["tools"] == ["utility_tool"]
@then("nodes with retry_policy should be converted")
def step_nodes_with_retry_policy_converted(context: Context):
"""Verify nodes with retry_policy are converted (lines 199-200)."""
route = context.result_route
# Check agent_node has retry_policy
agent_node = route.nodes["agent_node"]
assert "retry_policy" in agent_node
assert agent_node["retry_policy"] == {"max_retries": 5, "backoff": "exponential"}
# Check function_node has retry_policy
function_node = route.nodes["function_node"]
assert "retry_policy" in function_node
assert function_node["retry_policy"] == {"max_retries": 3}
@then("nodes with timeout should be converted")
def step_nodes_with_timeout_converted(context: Context):
"""Verify nodes with timeout are converted (lines 201-202)."""
route = context.result_route
# Check agent_node has timeout
agent_node = route.nodes["agent_node"]
assert "timeout" in agent_node
assert agent_node["timeout"] == 60
# Check function_node has timeout
function_node = route.nodes["function_node"]
assert "timeout" in function_node
assert function_node["timeout"] == 30
@then("edges with conditions should be converted")
def step_edges_with_conditions_converted(context: Context):
"""Verify edges with conditions are converted (lines 212-213)."""
route = context.result_route
# Find edge with condition
edge_with_condition = None
edge_without_condition = None
for edge in route.edges:
if "condition" in edge:
edge_with_condition = edge
else:
edge_without_condition = edge
# Verify edge with condition
assert edge_with_condition is not None
assert edge_with_condition["condition"] == "input_ready"
# Verify edge without condition doesn't have condition key
assert edge_without_condition is not None
assert "condition" not in edge_without_condition
@given("I have a hot stream RouteConfig")
def step_create_hot_stream_route_config(context: Context):
"""Create a hot stream RouteConfig."""
context.hot_stream_route = RouteConfig(
name="hot_stream",
type=RouteType.STREAM,
stream_type=StreamType.HOT,
operators=[{"type": "map"}],
)
@when("I analyze stream complexity")
def step_analyze_stream_complexity(context: Context):
"""Analyze stream complexity."""
context.stream_analysis = RouteComplexityAnalyzer.analyze_route(context.hot_stream_route)
@then("line 273-274 should be executed for hot stream detection")
def step_lines_273_274_executed(context: Context):
"""Verify lines 273-274 are executed for hot stream detection."""
analysis = context.stream_analysis
# Check that hot stream feature is detected
features = analysis["features"]
has_hot_feature = any("hot" in str(feature).lower() for feature in features)
assert has_hot_feature, "Hot stream feature should be detected"
@given("I have a graph with multiple conditional edges")
def step_create_graph_with_conditional_edges(context: Context):
"""Create a graph with multiple conditional edges."""
context.conditional_graph = RouteConfig(
name="conditional_graph",
type=RouteType.GRAPH,
nodes={
"node1": {"type": "agent"},
"node2": {"type": "agent"},
"node3": {"type": "agent"},
},
edges=[
{"source": "start", "target": "node1"},
{"source": "node1", "target": "node2", "condition": "path_a"},
{"source": "node1", "target": "node3", "condition": "path_b"},
{"source": "node2", "target": "end", "condition": "final_check"},
],
)
@when("I analyze graph complexity")
def step_analyze_graph_complexity(context: Context):
"""Analyze graph complexity."""
context.graph_analysis = RouteComplexityAnalyzer.analyze_route(context.conditional_graph)
@then("lines 303-304 should be executed for conditional edge counting")
def step_lines_303_304_executed(context: Context):
"""Verify lines 303-304 are executed for conditional edge counting."""
analysis = context.graph_analysis
# Should detect 3 conditional edges
features = analysis["features"]
has_conditional_feature = any("conditional" in str(feature).lower() for feature in features)
assert has_conditional_feature, "Conditional edges feature should be detected"
@given("I have a stream with complexity score of 8")
def step_create_stream_score_8(context: Context):
"""Create a stream that will have complexity score of 8."""
# Score calculation: 1 (base) + 6 (operators) + 2 (routing) = 9, close to 8
context.complex_stream_score = 8
@when("I get stream recommendation")
def step_get_stream_recommendation(context: Context):
"""Get stream recommendation."""
context.stream_recommendation = RouteComplexityAnalyzer._get_stream_recommendation(context.complex_stream_score)
@then("line 328 should be executed")
def step_line_328_executed(context: Context):
"""Verify line 328 is executed (complex stream recommendation)."""
recommendation = context.stream_recommendation
assert "graph" in recommendation.lower(), "Should recommend considering graph for complex streams"
@given("I have a graph with complexity score of 18")
def step_create_graph_score_18(context: Context):
"""Create a graph that will have complexity score of 18."""
context.advanced_graph_score = 18
@when("I get graph recommendation")
def step_get_graph_recommendation(context: Context):
"""Get graph recommendation."""
context.graph_recommendation = RouteComplexityAnalyzer._get_graph_recommendation(context.advanced_graph_score)
@then("line 340 should be executed")
def step_line_340_executed(context: Context):
"""Verify line 340 is executed (advanced graph recommendation)."""
recommendation = context.graph_recommendation
assert "features" in recommendation.lower(), "Should recommend feature evaluation for advanced graphs"
@given("I have requirements with needs_state and needs_conditionals true")
def step_create_state_conditionals_requirements(context: Context):
"""Create requirements with needs_state and needs_conditionals true."""
context.state_conditionals_reqs = {
"needs_state": True,
"needs_conditionals": True,
"needs_persistence": False,
}
@when("I get route type suggestion")
def step_get_route_type_suggestion(context: Context):
"""Get route type suggestion."""
if hasattr(context, "state_conditionals_reqs"):
context.route_suggestion = RouteComplexityAnalyzer.suggest_route_type(context.state_conditionals_reqs)
elif hasattr(context, "conditionals_not_continuous_reqs"):
context.route_suggestion = RouteComplexityAnalyzer.suggest_route_type(context.conditionals_not_continuous_reqs)
elif hasattr(context, "stateless_continuous_reqs"):
context.route_suggestion = RouteComplexityAnalyzer.suggest_route_type(context.stateless_continuous_reqs)
elif hasattr(context, "simple_reqs"):
context.route_suggestion = RouteComplexityAnalyzer.suggest_route_type(context.simple_reqs)
@then("line 351 should be executed")
def step_line_351_executed(context: Context):
"""Verify line 351 is executed."""
assert context.route_suggestion == RouteType.GRAPH
@then("it should return GRAPH")
def step_should_return_graph(context: Context):
"""Verify it returns GRAPH."""
assert context.route_suggestion == RouteType.GRAPH
@given("I have requirements with conditionals true but continuous false")
def step_create_conditionals_not_continuous_requirements(context: Context):
"""Create requirements with conditionals true but continuous false."""
context.conditionals_not_continuous_reqs = {
"needs_conditionals": True,
"is_continuous": False,
"needs_persistence": False,
"needs_state": False,
}
@then("line 353 should be executed")
def step_line_353_executed(context: Context):
"""Verify line 353 is executed."""
assert context.route_suggestion == RouteType.GRAPH
@given("I have requirements with stateless and continuous true")
def step_create_stateless_continuous_requirements(context: Context):
"""Create requirements with stateless and continuous true."""
context.stateless_continuous_reqs = {
"is_stateless": True,
"is_continuous": True,
"needs_persistence": False,
"needs_state": False,
"needs_conditionals": False,
}
@then("line 355 should be executed")
def step_line_355_executed(context: Context):
"""Verify line 355 is executed."""
assert context.route_suggestion == RouteType.STREAM
@then("it should return STREAM")
def step_should_return_stream(context: Context):
"""Verify it returns STREAM."""
assert context.route_suggestion == RouteType.STREAM
@given("I have simple requirements")
def step_create_simple_requirements(context: Context):
"""Create simple requirements (default case)."""
context.simple_reqs = {
"needs_persistence": False,
"needs_state": False,
"needs_conditionals": False,
"is_continuous": False,
"is_stateless": False,
}
@then("line 358 should be executed as default")
def step_line_358_executed_default(context: Context):
"""Verify line 358 is executed as default."""
assert context.route_suggestion == RouteType.STREAM