Skip to content

Commit

Permalink
test: add unit tests
Browse files Browse the repository at this point in the history
Signed-off-by: Valentin De Matos <vltn.dematos@gmail.com>
  • Loading branch information
Thytu committed Jan 3, 2025
1 parent e74262e commit e652950
Show file tree
Hide file tree
Showing 8 changed files with 552 additions and 0 deletions.
31 changes: 31 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
name: Run Tests

on:
pull_request:
branches: [ main ]
push:
branches: [ main ]

jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.10", "3.11"]

steps:
- uses: actions/checkout@v4

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}

- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -e ".[test]"
- name: Run tests with pytest
run: |
pytest
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
[![License: Apache 2.0](https://img.shields.io/badge/license-Apache%202.0-yellow.svg)](https://opensource.org/licenses/Apache-2.0)
[![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/)
[![PyPI version](https://badge.fury.io/py/agentarium.svg)](https://badge.fury.io/py/agentarium)
[![Tests](https://github.com/thytu/Agentarium/actions/workflows/test.yml/badge.svg)](https://github.com/thytu/Agentarium/actions/workflows/test.yml)

A powerful Python framework for managing and orchestrating AI agents with ease. Agentarium provides a flexible and intuitive way to create, manage, and coordinate interactions between multiple AI agents in various environments.

Expand Down
12 changes: 12 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,19 @@ dependencies = [
"PyYAML>=6.0.1",
"boto3>=1.35.86",
"aisuite>=0.1.7",
"dill>=0.3.8",
]

[project.optional-dependencies]
test = [
"pytest>=7.0.0",
"pytest-cov>=4.0.0",
]

[tool.pytest.ini_options]
testpaths = ["tests"]
python_files = ["test_*.py"]
addopts = "-v --cov=agentarium --cov-report=term-missing --cov-fail-under=80"

[project.urls]
Homepage = "https://github.com/thytu/Agentarium"
50 changes: 50 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import os
import pytest

from agentarium import Agent
from agentarium.CheckpointManager import CheckpointManager
from agentarium.AgentInteractionManager import AgentInteractionManager


@pytest.fixture(autouse=True)
def cleanup_checkpoint_files():
"""Automatically clean up any checkpoint files after each test."""
yield
# Clean up any .dill files in the current directory
for file in os.listdir():
if file.endswith('.dill'):
os.remove(file)


@pytest.fixture
def base_agent():
"""Create a basic agent for testing."""
return Agent.create_agent(
name="TestAgent",
age=25,
occupation="Software Engineer",
location="Test City",
bio="A test agent"
)


@pytest.fixture
def interaction_manager():
"""Create a fresh interaction manager for testing."""
return AgentInteractionManager()


@pytest.fixture
def checkpoint_manager():
"""Create a test checkpoint manager."""
manager = CheckpointManager("test_checkpoint")
yield manager
# Cleanup is handled by cleanup_checkpoint_files fixture


@pytest.fixture
def agent_pair():
"""Create a pair of agents for interaction testing."""
alice = Agent.create_agent(name="Alice")
bob = Agent.create_agent(name="Bob")
return alice, bob
135 changes: 135 additions & 0 deletions tests/test_action.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
import pytest
from agentarium import Action, Agent

def test_action_creation():
"""Test creating an action with valid parameters."""
def test_function(*args, **kwargs):
return {"result": "success"}

action = Action(
name="test",
description="A test action",
parameters=["param1", "param2"],
function=test_function
)

assert action.name == "test"
assert action.description == "A test action"
assert action.parameters == ["param1", "param2"]
assert action.function is not None

def test_action_single_parameter():
"""Test creating an action with a single parameter string."""
def test_function(*args, **kwargs):
return {"result": "success"}

# Test with a single parameter string
action = Action(
name="test",
description="A test action",
parameters="param1",
function=test_function
)

assert action.parameters == ["param1"]

# Test with a list of parameters
action = Action(
name="test",
description="A test action",
parameters=["param1"],
function=test_function
)

assert action.parameters == ["param1"]


def test_invalid_action_name():
"""Test that action creation fails with invalid name."""
def test_function(*args, **kwargs):
return {"result": "success"}

with pytest.raises(ValueError):
Action(
name="",
description="A test action",
parameters=["param1"],
function=test_function
)


def test_invalid_parameters():
"""Test that action creation fails with invalid parameters."""
def test_function(*args, **kwargs):
return {"result": "success"}

# Test empty parameter name
with pytest.raises(ValueError):
Action(
name="test",
description="A test action",
parameters=[""],
function=test_function
)

# Test non-string parameter
with pytest.raises(ValueError):
Action(
name="test",
description="A test action",
parameters=[123],
function=test_function
)


def test_action_format():
"""Test the action format string generation."""
def test_function(*args, **kwargs):
return {"result": "success"}

action = Action(
name="test",
description="A test action",
parameters=["param1", "param2"],
function=test_function
)

expected_format = "[test][param1][param2]"
assert action.get_format() == expected_format


def test_action_execution():
"""Test executing an action with an agent."""
def test_function(*args, **kwargs):
agent = kwargs["agent"]
return {"message": f"Action executed by {agent.name}"}

action = Action(
name="test",
description="A test action",
parameters=["param"],
function=test_function
)

agent = Agent.create_agent(name="TestAgent")
result = action.function("test_param", agent=agent)

assert result["action"] == "test"
assert "message" in result
assert "TestAgent" in result["message"]


def test_action_without_agent():
"""Test that action execution fails without agent in kwargs."""
def test_function(*args, **kwargs):
return {"result": "success"}

action = Action(
name="test",
description="A test action",
parameters=["param"],
function=test_function
)

with pytest.raises(RuntimeError):
action.function("test_param")
116 changes: 116 additions & 0 deletions tests/test_agent.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
import pytest

from agentarium import Agent, Action
from agentarium.constant import DefaultValue


def test_agent_creation():
"""Test basic agent creation with default and custom values."""
# Test with default values
agent = Agent.create_agent(bio="A test agent") # prevents the LLM from generating a bio
assert agent.agent_id is not None
assert agent.name is not None
assert agent.age is not None
assert agent.occupation is not None
assert agent.location is not None
assert agent.bio is not None

# Test with custom values
custom_agent = Agent.create_agent(
name="Alice",
age=25,
occupation="Software Engineer",
location="San Francisco",
bio="A passionate software engineer"
)
assert custom_agent.name == "Alice"
assert custom_agent.age == 25
assert custom_agent.occupation == "Software Engineer"
assert custom_agent.location == "San Francisco"
assert custom_agent.bio == "A passionate software engineer"


def test_agent_default_actions():
"""Test that agents are created with default actions."""
agent = Agent.create_agent()
assert "talk" in agent._actions
assert "think" in agent._actions


def test_agent_custom_actions():
"""Test adding and using custom actions."""
def custom_action(*args, **kwargs):
agent = kwargs["agent"]
return {"message": f"Custom action by {agent.name}"}

custom_action_obj = Action(
name="custom",
description="A custom action",
parameters=["message"],
function=custom_action
)

agent = Agent.create_agent(name="Bob", bio="A test agent")
agent.add_action(custom_action_obj)

assert "custom" in agent._actions
result = agent.execute_action("custom", "test message")
assert result["action"] == "custom"
assert "message" in result


def test_agent_interaction():
"""Test basic interaction between agents."""
alice = Agent.create_agent(name="Alice")
bob = Agent.create_agent(name="Bob")

message = "Hello Bob!"
alice.talk_to(bob, message)

# Check Alice's interactions
alice_interactions = alice.get_interactions()
assert len(alice_interactions) == 1
assert alice_interactions[0].sender == alice
assert alice_interactions[0].receiver == bob
assert alice_interactions[0].message == message

# Check Bob's interactions
bob_interactions = bob.get_interactions()
assert len(bob_interactions) == 1
assert bob_interactions[0].sender == alice
assert bob_interactions[0].receiver == bob
assert bob_interactions[0].message == message


def test_agent_think():
"""Test agent's ability to think."""
agent = Agent.create_agent(name="Alice")
thought = "I should learn more about AI"

agent.think(thought)

interactions = agent.get_interactions()
assert len(interactions) == 1
assert interactions[0].sender == agent
assert interactions[0].receiver == agent
assert interactions[0].message == thought


def test_invalid_action():
"""Test handling of invalid actions."""
agent = Agent.create_agent()

with pytest.raises(RuntimeError):
agent.execute_action("nonexistent_action", "test")


def test_agent_reset():
"""Test resetting agent state."""
agent = Agent.create_agent()
agent.think("Initial thought")

assert len(agent.get_interactions()) == 1

agent.reset()
assert len(agent.get_interactions()) == 0
assert len(agent.storage) == 0
Loading

0 comments on commit e652950

Please sign in to comment.