aider/tests/basic/test_batch_editing.py
Emasoft 8f3cfe1985 Added logic to split and batch the changes in architect mode. In this way editor models with small input context limits will be able to handle the code changes just as well as the more expensive models.
added option to use the new batch editing feature or to stick to the
original architect workflow that makes the changes in one go.

Added parameter `--use-batch-editing` and --no-use-batch-editing` as
command line argument.

Added option `use-batch-editing` to yaml configuration file.
2025-05-17 07:51:40 +02:00

103 lines
No EOL
4.6 KiB
Python

import unittest
from unittest.mock import MagicMock, patch
from aider.coders.architect_coder import ArchitectCoder
from aider.io import InputOutput
from aider.models import Model
class TestBatchEditing(unittest.TestCase):
def setUp(self):
self.GPT35 = Model("gpt-3.5-turbo")
self.webbrowser_patcher = patch("aider.io.webbrowser.open")
self.mock_webbrowser = self.webbrowser_patcher.start()
def tearDown(self):
self.webbrowser_patcher.stop()
def test_batch_editing_default_value(self):
"""Test that the default value for use_batch_editing is False"""
# Create an architect coder with default settings
io = InputOutput(yes=True)
with patch("aider.coders.architect_coder.AskCoder.__init__", return_value=None):
coder = ArchitectCoder(main_model=self.GPT35, io=io)
# Check that the default value is False
self.assertFalse(coder.use_batch_editing)
def test_batch_editing_parameter_passing(self):
"""Test that the use_batch_editing parameter is correctly passed to the ArchitectCoder"""
io = InputOutput(yes=True)
# Test with explicit True setting
with patch("aider.coders.architect_coder.AskCoder.__init__", return_value=None):
coder = ArchitectCoder(main_model=self.GPT35, io=io, use_batch_editing=True)
self.assertTrue(coder.use_batch_editing)
# Test with explicit False setting
with patch("aider.coders.architect_coder.AskCoder.__init__", return_value=None):
coder = ArchitectCoder(main_model=self.GPT35, io=io, use_batch_editing=False)
self.assertFalse(coder.use_batch_editing)
def test_batch_editing_usage_in_reply_completed(self):
"""Test that the use_batch_editing attribute controls the flow in reply_completed"""
io = InputOutput(yes=True)
io.confirm_ask = MagicMock(return_value=True)
# Create an ArchitectCoder with use_batch_editing=True
with patch("aider.coders.architect_coder.AskCoder.__init__", return_value=None):
coder = ArchitectCoder(main_model=self.GPT35, io=io)
# Set up the necessary attributes manually
coder.io = io # Need to set this explicitly since we're mocking __init__
coder.main_model = self.GPT35
coder.auto_accept_architect = True
coder.verbose = False
coder.total_cost = 0
coder.cur_messages = []
coder.done_messages = []
coder.aider_commit_hashes = None
coder.move_back_cur_messages = MagicMock()
# Mock the split_response_by_natural_delimiters method
coder.split_response_by_natural_delimiters = MagicMock()
coder.split_response_by_natural_delimiters.return_value = ["chunk1", "chunk2"]
# Mock editor_coder creation and execution
mock_editor = MagicMock()
mock_editor.total_cost = 0
mock_editor.aider_commit_hashes = set()
# Test with use_batch_editing=True
coder.use_batch_editing = True
with patch("aider.coders.architect_coder.Coder.create", return_value=mock_editor):
# Set partial response content
coder.partial_response_content = "Make these changes to the code"
# Call reply_completed
coder.reply_completed()
# Verify split_response_by_natural_delimiters was called
coder.split_response_by_natural_delimiters.assert_called_once_with("Make these changes to the code")
# Verify Coder.create was called twice (once for each chunk)
self.assertEqual(mock_editor.run.call_count, 2)
# Reset mocks
coder.split_response_by_natural_delimiters.reset_mock()
mock_editor.run.reset_mock()
# Test with use_batch_editing=False
coder.use_batch_editing = False
with patch("aider.coders.architect_coder.Coder.create", return_value=mock_editor):
# Call reply_completed
coder.reply_completed()
# Verify split_response_by_natural_delimiters was NOT called
coder.split_response_by_natural_delimiters.assert_not_called()
# Verify Coder.create was called once for the entire content
mock_editor.run.assert_called_once()
if __name__ == "__main__":
unittest.main()