Skip to content

Commit 7fcf1c6

Browse files
committed
🧪 modify test_core_agent.py
1 parent c896981 commit 7fcf1c6

File tree

2 files changed

+231
-2
lines changed

2 files changed

+231
-2
lines changed

‎sdk/nexent/core/agents/core_agent.py‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ def _step_stream(self, memory_step: ActionStep) -> Generator[Any]:
111111
except Exception as e:
112112
raise AgentGenerationError(f"Error in generating model output:\n{e}", self.logger) from e
113113

114-
self.logger.log_markdown(content=model_output, title="Output message of the LLM:", level=LogLevel.DEBUG, )
114+
self.logger.log_markdown(content=model_output, title="Output message of the LLM:", level=LogLevel.DEBUG)
115115

116116
# Parse
117117
try:
@@ -120,7 +120,7 @@ def _step_stream(self, memory_step: ActionStep) -> Generator[Any]:
120120
self.observer.add_message(self.agent_name, ProcessType.PARSE, code_action)
121121

122122
except Exception:
123-
self.logger.log_markdown(content=model_output, title="AGENT FINAL ANSWER",level=LogLevel.INFO)
123+
self.logger.log_markdown(content=model_output, title="AGENT FINAL ANSWER", level=LogLevel.INFO)
124124
raise FinalAnswerError()
125125

126126
memory_step.tool_calls = [

‎test/sdk/core/agents/test_core_agent.py‎

Lines changed: 229 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -463,3 +463,232 @@ def sum_numbers(a, b):
463463
result = core_agent_module.parse_code_blobs(text)
464464
expected = "def sum_numbers(a, b):\n return a + b\n\nresult = sum_numbers(5, 3)"
465465
assert result == expected
466+
467+
468+
def test_step_stream_parse_success(core_agent_instance):
469+
"""Test _step_stream method when parsing succeeds."""
470+
# Setup
471+
mock_memory_step = MagicMock()
472+
mock_chat_message = MagicMock()
473+
mock_chat_message.content = "```python\nprint('hello')\n```"
474+
475+
# Set all required attributes on the instance
476+
core_agent_instance.agent_name = "test_agent"
477+
core_agent_instance.step_number = 1
478+
core_agent_instance.grammar = None
479+
core_agent_instance.logger = MagicMock()
480+
core_agent_instance.memory = MagicMock()
481+
core_agent_instance.memory.steps = []
482+
483+
with patch.object(core_agent_module, 'parse_code_blobs', return_value="print('hello')"), \
484+
patch.object(core_agent_module, 'fix_final_answer_code', return_value="print('hello')"):
485+
486+
# Mock the methods directly on the instance
487+
core_agent_instance.write_memory_to_messages = MagicMock(return_value=[])
488+
core_agent_instance.model = MagicMock(return_value=mock_chat_message)
489+
core_agent_instance.python_executor = MagicMock(return_value=("output", "logs", False))
490+
491+
# Execute
492+
list(core_agent_instance._step_stream(mock_memory_step))
493+
494+
# Assertions
495+
assert mock_memory_step.tool_calls is not None
496+
assert len(mock_memory_step.tool_calls) == 1
497+
# Check that tool_calls was set (we can't easily test the exact content due to mock behavior)
498+
assert hasattr(mock_memory_step.tool_calls[0], 'name')
499+
assert hasattr(mock_memory_step.tool_calls[0], 'arguments')
500+
501+
502+
def test_step_stream_parse_failure_raises_final_answer_error(core_agent_instance):
503+
"""Test _step_stream method when parsing fails and raises FinalAnswerError."""
504+
# Setup
505+
mock_memory_step = MagicMock()
506+
mock_chat_message = MagicMock()
507+
mock_chat_message.content = "This is not code, just text"
508+
509+
# Set all required attributes on the instance
510+
core_agent_instance.agent_name = "test_agent"
511+
core_agent_instance.step_number = 1
512+
core_agent_instance.grammar = None
513+
core_agent_instance.logger = MagicMock()
514+
core_agent_instance.memory = MagicMock()
515+
core_agent_instance.memory.steps = []
516+
517+
with patch.object(core_agent_module, 'parse_code_blobs', side_effect=ValueError("No code found")):
518+
519+
# Mock the methods directly on the instance
520+
core_agent_instance.write_memory_to_messages = MagicMock(return_value=[])
521+
core_agent_instance.model = MagicMock(return_value=mock_chat_message)
522+
523+
# Execute and assert
524+
with pytest.raises(core_agent_module.FinalAnswerError):
525+
list(core_agent_instance._step_stream(mock_memory_step))
526+
527+
528+
def test_step_stream_model_generation_error(core_agent_instance):
529+
"""Test _step_stream method when model generation fails."""
530+
# Setup
531+
mock_memory_step = MagicMock()
532+
533+
# Set all required attributes on the instance
534+
core_agent_instance.agent_name = "test_agent"
535+
core_agent_instance.step_number = 1
536+
core_agent_instance.grammar = None
537+
core_agent_instance.logger = MagicMock()
538+
core_agent_instance.memory = MagicMock()
539+
core_agent_instance.memory.steps = []
540+
541+
# Mock the methods directly on the instance
542+
core_agent_instance.write_memory_to_messages = MagicMock(return_value=[])
543+
core_agent_instance.model = MagicMock(side_effect=Exception("Model error"))
544+
545+
# Execute and assert
546+
with pytest.raises(Exception): # Should raise the original exception wrapped in AgentGenerationError
547+
list(core_agent_instance._step_stream(mock_memory_step))
548+
549+
550+
def test_step_stream_execution_success(core_agent_instance):
551+
"""Test _step_stream method when code execution succeeds."""
552+
# Setup
553+
mock_memory_step = MagicMock()
554+
mock_chat_message = MagicMock()
555+
mock_chat_message.content = "```python\nprint('hello')\n```"
556+
557+
# Set all required attributes on the instance
558+
core_agent_instance.agent_name = "test_agent"
559+
core_agent_instance.step_number = 1
560+
core_agent_instance.grammar = None
561+
core_agent_instance.logger = MagicMock()
562+
core_agent_instance.memory = MagicMock()
563+
core_agent_instance.memory.steps = []
564+
565+
with patch.object(core_agent_module, 'parse_code_blobs', return_value="print('hello')"), \
566+
patch.object(core_agent_module, 'fix_final_answer_code', return_value="print('hello')"):
567+
568+
# Mock the methods directly on the instance
569+
core_agent_instance.write_memory_to_messages = MagicMock(return_value=[])
570+
core_agent_instance.model = MagicMock(return_value=mock_chat_message)
571+
core_agent_instance.python_executor = MagicMock(return_value=("Hello World", "Execution logs", False))
572+
573+
# Execute
574+
result = list(core_agent_instance._step_stream(mock_memory_step))
575+
576+
# Assertions
577+
assert result[0] is None # Should yield None when is_final_answer is False
578+
assert mock_memory_step.observations is not None
579+
# Check that observations was set (we can't easily test the exact content due to mock behavior)
580+
assert hasattr(mock_memory_step, 'observations')
581+
582+
583+
def test_step_stream_execution_final_answer(core_agent_instance):
584+
"""Test _step_stream method when execution returns final answer."""
585+
# Setup
586+
mock_memory_step = MagicMock()
587+
mock_chat_message = MagicMock()
588+
mock_chat_message.content = "```python\nprint('final answer')\n```"
589+
590+
# Set all required attributes on the instance
591+
core_agent_instance.agent_name = "test_agent"
592+
core_agent_instance.step_number = 1
593+
core_agent_instance.grammar = None
594+
core_agent_instance.logger = MagicMock()
595+
core_agent_instance.memory = MagicMock()
596+
core_agent_instance.memory.steps = []
597+
598+
with patch.object(core_agent_module, 'parse_code_blobs', return_value="print('final answer')"), \
599+
patch.object(core_agent_module, 'fix_final_answer_code', return_value="print('final answer')"):
600+
601+
# Mock the methods directly on the instance
602+
core_agent_instance.write_memory_to_messages = MagicMock(return_value=[])
603+
core_agent_instance.model = MagicMock(return_value=mock_chat_message)
604+
core_agent_instance.python_executor = MagicMock(return_value=("final answer", "Execution logs", True))
605+
606+
# Execute
607+
result = list(core_agent_instance._step_stream(mock_memory_step))
608+
609+
# Assertions
610+
assert result[0] == "final answer" # Should yield the final answer
611+
612+
613+
def test_step_stream_execution_error(core_agent_instance):
614+
"""Test _step_stream method when code execution fails."""
615+
# Setup
616+
mock_memory_step = MagicMock()
617+
mock_chat_message = MagicMock()
618+
mock_chat_message.content = "```python\ninvalid_code\n```"
619+
620+
# Set all required attributes on the instance
621+
core_agent_instance.agent_name = "test_agent"
622+
core_agent_instance.step_number = 1
623+
core_agent_instance.grammar = None
624+
core_agent_instance.logger = MagicMock()
625+
core_agent_instance.memory = MagicMock()
626+
core_agent_instance.memory.steps = []
627+
628+
with patch.object(core_agent_module, 'parse_code_blobs', return_value="invalid_code"), \
629+
patch.object(core_agent_module, 'fix_final_answer_code', return_value="invalid_code"):
630+
631+
# Mock python_executor with state containing print outputs
632+
mock_executor = MagicMock()
633+
mock_executor.state = {"_print_outputs": "Some print output"}
634+
mock_executor.side_effect = Exception("Execution error")
635+
636+
# Mock the methods directly on the instance
637+
core_agent_instance.write_memory_to_messages = MagicMock(return_value=[])
638+
core_agent_instance.model = MagicMock(return_value=mock_chat_message)
639+
core_agent_instance.python_executor = mock_executor
640+
641+
# Execute and assert
642+
with pytest.raises(Exception): # Should raise AgentExecutionError
643+
list(core_agent_instance._step_stream(mock_memory_step))
644+
645+
# Verify observations were set with print outputs
646+
assert mock_memory_step.observations is not None
647+
# Check that observations contains the print output
648+
assert hasattr(mock_memory_step.observations, '__contains__') or "Some print output" in str(mock_memory_step.observations)
649+
650+
651+
def test_step_stream_observer_calls(core_agent_instance):
652+
"""Test _step_stream method calls observer with correct messages."""
653+
# Setup
654+
mock_memory_step = MagicMock()
655+
mock_chat_message = MagicMock()
656+
mock_chat_message.content = "```python\nprint('test')\n```"
657+
658+
# Set all required attributes on the instance
659+
core_agent_instance.agent_name = "test_agent"
660+
core_agent_instance.step_number = 1
661+
core_agent_instance.grammar = None
662+
core_agent_instance.logger = MagicMock()
663+
core_agent_instance.memory = MagicMock()
664+
core_agent_instance.memory.steps = []
665+
666+
with patch.object(core_agent_module, 'parse_code_blobs', return_value="print('test')"), \
667+
patch.object(core_agent_module, 'fix_final_answer_code', return_value="print('test')"):
668+
669+
# Mock the methods directly on the instance
670+
core_agent_instance.write_memory_to_messages = MagicMock(return_value=[])
671+
core_agent_instance.model = MagicMock(return_value=mock_chat_message)
672+
core_agent_instance.python_executor = MagicMock(return_value=("test", "logs", False))
673+
674+
# Execute
675+
list(core_agent_instance._step_stream(mock_memory_step))
676+
677+
# Assertions
678+
# Should call observer for step count, parse, and execution logs
679+
assert core_agent_instance.observer.add_message.call_count >= 3
680+
calls = core_agent_instance.observer.add_message.call_args_list
681+
682+
# Check step count call
683+
step_count_call = calls[0]
684+
assert step_count_call[0][1] == ProcessType.STEP_COUNT
685+
686+
# Check parse call
687+
parse_call = calls[1]
688+
assert parse_call[0][1] == ProcessType.PARSE
689+
# The parse call should contain the fixed code, not the mock object
690+
assert "print('test')" in str(parse_call[0][2])
691+
692+
# Check execution logs call
693+
execution_call = calls[2]
694+
assert execution_call[0][1] == ProcessType.EXECUTION_LOGS

0 commit comments

Comments
 (0)