diff options
Diffstat (limited to 'autogpts/autogpt/tests/unit/test_commands.py')
-rw-r--r-- | autogpts/autogpt/tests/unit/test_commands.py | 239 |
1 files changed, 239 insertions, 0 deletions
diff --git a/autogpts/autogpt/tests/unit/test_commands.py b/autogpts/autogpt/tests/unit/test_commands.py new file mode 100644 index 000000000..a939ec4d2 --- /dev/null +++ b/autogpts/autogpt/tests/unit/test_commands.py @@ -0,0 +1,239 @@ +from __future__ import annotations + +import os +import shutil +import sys +from pathlib import Path +from typing import TYPE_CHECKING + +import pytest + +if TYPE_CHECKING: + from autogpt.agents import Agent, BaseAgent + +from autogpt.core.utils.json_schema import JSONSchema +from autogpt.models.command import Command, CommandParameter +from autogpt.models.command_registry import CommandRegistry + +PARAMETERS = [ + CommandParameter( + "arg1", + spec=JSONSchema( + type=JSONSchema.Type.INTEGER, + description="Argument 1", + required=True, + ), + ), + CommandParameter( + "arg2", + spec=JSONSchema( + type=JSONSchema.Type.STRING, + description="Argument 2", + required=False, + ), + ), +] + + +def example_command_method(arg1: int, arg2: str, agent: BaseAgent) -> str: + """Example function for testing the Command class.""" + # This function is static because it is not used by any other test cases. + return f"{arg1} - {arg2}" + + +def test_command_creation(): + """Test that a Command object can be created with the correct attributes.""" + cmd = Command( + name="example", + description="Example command", + method=example_command_method, + parameters=PARAMETERS, + ) + + assert cmd.name == "example" + assert cmd.description == "Example command" + assert cmd.method == example_command_method + assert ( + str(cmd) + == "example: Example command. Params: (arg1: integer, arg2: Optional[string])" + ) + + +@pytest.fixture +def example_command(): + yield Command( + name="example", + description="Example command", + method=example_command_method, + parameters=PARAMETERS, + ) + + +def test_command_call(example_command: Command, agent: Agent): + """Test that Command(*args) calls and returns the result of method(*args).""" + result = example_command(arg1=1, arg2="test", agent=agent) + assert result == "1 - test" + + +def test_command_call_with_invalid_arguments(example_command: Command, agent: Agent): + """Test that calling a Command object with invalid arguments raises a TypeError.""" + with pytest.raises(TypeError): + example_command(arg1="invalid", does_not_exist="test", agent=agent) + + +def test_register_command(example_command: Command): + """Test that a command can be registered to the registry.""" + registry = CommandRegistry() + + registry.register(example_command) + + assert registry.get_command(example_command.name) == example_command + assert len(registry.commands) == 1 + + +def test_unregister_command(example_command: Command): + """Test that a command can be unregistered from the registry.""" + registry = CommandRegistry() + + registry.register(example_command) + registry.unregister(example_command) + + assert len(registry.commands) == 0 + assert example_command.name not in registry + + +@pytest.fixture +def example_command_with_aliases(example_command: Command): + example_command.aliases = ["example_alias", "example_alias_2"] + return example_command + + +def test_register_command_aliases(example_command_with_aliases: Command): + """Test that a command can be registered to the registry.""" + registry = CommandRegistry() + command = example_command_with_aliases + + registry.register(command) + + assert command.name in registry + assert registry.get_command(command.name) == command + for alias in command.aliases: + assert registry.get_command(alias) == command + assert len(registry.commands) == 1 + + +def test_unregister_command_aliases(example_command_with_aliases: Command): + """Test that a command can be unregistered from the registry.""" + registry = CommandRegistry() + command = example_command_with_aliases + + registry.register(command) + registry.unregister(command) + + assert len(registry.commands) == 0 + assert command.name not in registry + for alias in command.aliases: + assert alias not in registry + + +def test_command_in_registry(example_command_with_aliases: Command): + """Test that `command_name in registry` works.""" + registry = CommandRegistry() + command = example_command_with_aliases + + assert command.name not in registry + assert "nonexistent_command" not in registry + + registry.register(command) + + assert command.name in registry + assert "nonexistent_command" not in registry + for alias in command.aliases: + assert alias in registry + + +def test_get_command(example_command: Command): + """Test that a command can be retrieved from the registry.""" + registry = CommandRegistry() + + registry.register(example_command) + retrieved_cmd = registry.get_command(example_command.name) + + assert retrieved_cmd == example_command + + +def test_get_nonexistent_command(): + """Test that attempting to get a nonexistent command raises a KeyError.""" + registry = CommandRegistry() + + assert registry.get_command("nonexistent_command") is None + assert "nonexistent_command" not in registry + + +def test_call_command(agent: Agent): + """Test that a command can be called through the registry.""" + registry = CommandRegistry() + cmd = Command( + name="example", + description="Example command", + method=example_command_method, + parameters=PARAMETERS, + ) + + registry.register(cmd) + result = registry.call("example", arg1=1, arg2="test", agent=agent) + + assert result == "1 - test" + + +def test_call_nonexistent_command(agent: Agent): + """Test that attempting to call a nonexistent command raises a KeyError.""" + registry = CommandRegistry() + + with pytest.raises(KeyError): + registry.call("nonexistent_command", arg1=1, arg2="test", agent=agent) + + +def test_import_mock_commands_module(): + """Test that the registry can import a module with mock command plugins.""" + registry = CommandRegistry() + mock_commands_module = "tests.mocks.mock_commands" + + registry.import_command_module(mock_commands_module) + + assert "function_based_cmd" in registry + assert registry.commands["function_based_cmd"].name == "function_based_cmd" + assert ( + registry.commands["function_based_cmd"].description + == "Function-based test command" + ) + + +def test_import_temp_command_file_module(tmp_path: Path): + """ + Test that the registry can import a command plugins module from a temp file. + Args: + tmp_path (pathlib.Path): Path to a temporary directory. + """ + registry = CommandRegistry() + + # Create a temp command file + src = Path(os.getcwd()) / "tests/mocks/mock_commands.py" + temp_commands_file = tmp_path / "mock_commands.py" + shutil.copyfile(src, temp_commands_file) + + # Add the temp directory to sys.path to make the module importable + sys.path.append(str(tmp_path)) + + temp_commands_module = "mock_commands" + registry.import_command_module(temp_commands_module) + + # Remove the temp directory from sys.path + sys.path.remove(str(tmp_path)) + + assert "function_based_cmd" in registry + assert registry.commands["function_based_cmd"].name == "function_based_cmd" + assert ( + registry.commands["function_based_cmd"].description + == "Function-based test command" + ) |