test_guess_success.py 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. import json
  2. from unittest.mock import MagicMock, patch
  3. from openhands.core.config import LLMConfig
  4. from openhands.events.action.message import MessageAction
  5. from openhands.llm import LLM
  6. from openhands.resolver.github_issue import GithubIssue
  7. from openhands.resolver.issue_definitions import IssueHandler, PRHandler
  8. def test_guess_success_multiline_explanation():
  9. # Mock data
  10. issue = GithubIssue(
  11. owner='test',
  12. repo='test',
  13. number=1,
  14. title='Test Issue',
  15. body='Test body',
  16. thread_comments=None,
  17. review_comments=None,
  18. )
  19. history = [MessageAction(content='Test message')]
  20. llm_config = LLMConfig(model='test', api_key='test')
  21. # Create a mock response with multi-line explanation
  22. mock_response = MagicMock()
  23. mock_response.choices = [
  24. MagicMock(
  25. message=MagicMock(
  26. content="""--- success
  27. true
  28. --- explanation
  29. The PR successfully addressed the issue by:
  30. - Fixed bug A
  31. - Added test B
  32. - Updated documentation C
  33. Automatic fix generated by OpenHands 🙌"""
  34. )
  35. )
  36. ]
  37. # Use patch to mock the LLM completion call
  38. with patch.object(LLM, 'completion', return_value=mock_response) as mock_completion:
  39. # Create a handler instance
  40. handler = IssueHandler('test', 'test', 'test', llm_config)
  41. # Call guess_success
  42. success, _, explanation = handler.guess_success(issue, history)
  43. # Verify the results
  44. assert success is True
  45. assert 'The PR successfully addressed the issue by:' in explanation
  46. assert 'Fixed bug A' in explanation
  47. assert 'Added test B' in explanation
  48. assert 'Updated documentation C' in explanation
  49. assert 'Automatic fix generated by OpenHands' in explanation
  50. # Verify that LLM completion was called exactly once
  51. mock_completion.assert_called_once()
  52. def test_pr_handler_guess_success_with_thread_comments():
  53. # Create a PR handler instance
  54. llm_config = LLMConfig(model='test', api_key='test')
  55. handler = PRHandler('test-owner', 'test-repo', 'test-token', llm_config)
  56. # Create a mock issue with thread comments but no review comments
  57. issue = GithubIssue(
  58. owner='test-owner',
  59. repo='test-repo',
  60. number=1,
  61. title='Test PR',
  62. body='Test Body',
  63. thread_comments=['First comment', 'Second comment'],
  64. closing_issues=['Issue description'],
  65. review_comments=None,
  66. thread_ids=None,
  67. head_branch='test-branch',
  68. )
  69. # Create mock history
  70. history = [MessageAction(content='Fixed the issue by implementing X and Y')]
  71. # Create mock LLM config
  72. llm_config = LLMConfig(model='test-model', api_key='test-key')
  73. # Mock the LLM response
  74. mock_response = MagicMock()
  75. mock_response.choices = [
  76. MagicMock(
  77. message=MagicMock(
  78. content="""--- success
  79. true
  80. --- explanation
  81. The changes successfully address the feedback."""
  82. )
  83. )
  84. ]
  85. # Test the guess_success method
  86. with patch.object(LLM, 'completion', return_value=mock_response):
  87. success, success_list, explanation = handler.guess_success(issue, history)
  88. # Verify the results
  89. assert success is True
  90. assert success_list == [True]
  91. assert 'successfully address' in explanation
  92. assert len(json.loads(explanation)) == 1
  93. def test_pr_handler_guess_success_only_review_comments():
  94. # Create a PR handler instance
  95. llm_config = LLMConfig(model='test', api_key='test')
  96. handler = PRHandler('test-owner', 'test-repo', 'test-token', llm_config)
  97. # Create a mock issue with only review comments
  98. issue = GithubIssue(
  99. owner='test-owner',
  100. repo='test-repo',
  101. number=1,
  102. title='Test PR',
  103. body='Test Body',
  104. thread_comments=None,
  105. closing_issues=['Issue description'],
  106. review_comments=['Please fix the formatting', 'Add more tests'],
  107. thread_ids=None,
  108. head_branch='test-branch',
  109. )
  110. # Create mock history
  111. history = [MessageAction(content='Fixed the formatting and added more tests')]
  112. # Create mock LLM config
  113. llm_config = LLMConfig(model='test-model', api_key='test-key')
  114. # Mock the LLM response
  115. mock_response = MagicMock()
  116. mock_response.choices = [
  117. MagicMock(
  118. message=MagicMock(
  119. content="""--- success
  120. true
  121. --- explanation
  122. The changes successfully address the review comments."""
  123. )
  124. )
  125. ]
  126. # Test the guess_success method
  127. with patch.object(LLM, 'completion', return_value=mock_response):
  128. success, success_list, explanation = handler.guess_success(issue, history)
  129. # Verify the results
  130. assert success is True
  131. assert success_list == [True]
  132. assert (
  133. '["The changes successfully address the review comments."]' in explanation
  134. )
  135. def test_pr_handler_guess_success_no_comments():
  136. # Create a PR handler instance
  137. llm_config = LLMConfig(model='test', api_key='test')
  138. handler = PRHandler('test-owner', 'test-repo', 'test-token', llm_config)
  139. # Create a mock issue with no comments
  140. issue = GithubIssue(
  141. owner='test-owner',
  142. repo='test-repo',
  143. number=1,
  144. title='Test PR',
  145. body='Test Body',
  146. thread_comments=None,
  147. closing_issues=['Issue description'],
  148. review_comments=None,
  149. thread_ids=None,
  150. head_branch='test-branch',
  151. )
  152. # Create mock history
  153. history = [MessageAction(content='Fixed the issue')]
  154. # Create mock LLM config
  155. llm_config = LLMConfig(model='test-model', api_key='test-key')
  156. # Test that it returns appropriate message when no comments are present
  157. success, success_list, explanation = handler.guess_success(issue, history)
  158. assert success is False
  159. assert success_list is None
  160. assert explanation == 'No feedback was found to process'