test_action_github.py 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. from unittest.mock import MagicMock, call, patch
  2. import pytest
  3. from agenthub.dummy_agent.agent import DummyAgent
  4. from opendevin import config
  5. from opendevin.action.github import GitHubPushAction, GitHubSendPRAction
  6. from opendevin.controller.agent_controller import AgentController
  7. from opendevin.llm.llm import LLM
  8. from opendevin.observation.error import AgentErrorObservation
  9. from opendevin.observation.message import AgentMessageObservation
  10. from opendevin.observation.run import CmdOutputObservation
  11. from opendevin.schema.config import ConfigType
  12. @pytest.fixture
  13. def agent_controller():
  14. # Setup the environment variable
  15. config.config[ConfigType.SANDBOX_TYPE] = 'local'
  16. llm = LLM()
  17. agent = DummyAgent(llm=llm)
  18. controller = AgentController(agent)
  19. yield controller
  20. @pytest.mark.asyncio
  21. @patch.dict(config.config, {'GITHUB_TOKEN': 'fake_token'}, clear=True)
  22. @patch('random.choices')
  23. @patch('opendevin.controller.action_manager.ActionManager.run_command')
  24. async def test_run_push_successful(mock_run_command, mock_random_choices, agent_controller):
  25. # Setup mock for random.choices
  26. mock_random_choices.return_value = ['a', 'b', 'c', 'd', 'e']
  27. # Create a CmdOutputObservation instance for successful command execution
  28. successful_output = CmdOutputObservation(content='', command_id=1, command='', exit_code=0)
  29. # Setup the mock for run_command to return successful output
  30. mock_run_command.return_value = successful_output
  31. # Run the method
  32. push_action = GitHubPushAction(owner='owner', repo='repo', branch='branch')
  33. result = await push_action.run(agent_controller)
  34. # Verify the result is successful
  35. assert isinstance(result, CmdOutputObservation)
  36. assert result.exit_code == 0
  37. # Verify that the correct remote commands were sent
  38. expected_calls = [
  39. call(
  40. 'git remote add opendevin_temp_abcde https://fake_token@github.com/owner/repo.git',
  41. background=False,
  42. ),
  43. call('git push opendevin_temp_abcde branch', background=False),
  44. call('git remote remove opendevin_temp_abcde', background=False),
  45. ]
  46. mock_run_command.assert_has_calls(expected_calls)
  47. @pytest.mark.asyncio
  48. @patch('random.choices')
  49. @patch('opendevin.controller.action_manager.ActionManager.run_command')
  50. async def test_run_push_error_missing_token(
  51. mock_run_command, mock_random_choices, agent_controller
  52. ):
  53. # Run the method
  54. push_action = GitHubPushAction(owner='owner', repo='repo', branch='branch')
  55. result = await push_action.run(agent_controller)
  56. # Verify the result is an error due to missing token
  57. assert isinstance(result, AgentErrorObservation)
  58. assert (
  59. result.message
  60. == 'Oops. Something went wrong: GITHUB_TOKEN is not set'
  61. )
  62. @pytest.mark.asyncio
  63. @patch.dict(config.config, {'GITHUB_TOKEN': 'fake_token'}, clear=True)
  64. @patch('requests.post')
  65. async def test_run_pull_request_created_successfully(mock_post, agent_controller):
  66. # Set up the mock for the requests.post call to simulate a successful pull request creation
  67. mock_response = MagicMock()
  68. mock_response.status_code = 201
  69. mock_response.json.return_value = {'html_url': 'https://github.com/example/pull/1'}
  70. mock_post.return_value = mock_response
  71. # Run the method
  72. pr_action = GitHubSendPRAction(owner='owner', repo='repo', title='title', head='head', head_repo='head_repo', base='base', body='body')
  73. result = await pr_action.run(agent_controller)
  74. # Verify the result is a success observation
  75. assert isinstance(result, AgentMessageObservation)
  76. assert 'Pull request created successfully' in result.content
  77. assert 'https://github.com/example/pull/1' in result.content
  78. @pytest.mark.asyncio
  79. @patch('requests.post')
  80. @patch.dict(config.config, {'GITHUB_TOKEN': 'fake_token'}, clear=True)
  81. async def test_run_pull_request_creation_failed(mock_post, agent_controller):
  82. # Set up the mock for the requests.post call to simulate a failed pull request creation
  83. mock_response = MagicMock()
  84. mock_response.status_code = 400
  85. mock_response.text = 'Bad Request'
  86. mock_post.return_value = mock_response
  87. # Run the method
  88. pr_action = GitHubSendPRAction(owner='owner', repo='repo', title='title', head='head', head_repo='head_repo', base='base', body='body')
  89. result = await pr_action.run(agent_controller)
  90. # Verify the result is an error observation
  91. assert isinstance(result, AgentErrorObservation)
  92. assert 'Failed to create pull request' in result.content
  93. assert 'Status code: 400' in result.content
  94. assert 'Bad Request' in result.content
  95. @pytest.mark.asyncio
  96. async def test_run_error_missing_token(agent_controller):
  97. # Run the method
  98. pr_action = GitHubSendPRAction(owner='owner', repo='repo', title='title', head='head', head_repo='head_repo', base='base', body='body')
  99. result = await pr_action.run(agent_controller)
  100. # Verify the result is an error due to missing token
  101. assert isinstance(result, AgentErrorObservation)
  102. assert 'GITHUB_TOKEN is not set' in result.message