Spaces:
Sleeping
Sleeping
| # Testing | |
| ## Running Tests | |
| === "pytest (recommended)" | |
| ```bash | |
| uv run pytest # All tests | |
| uv run pytest -m unit # Unit tests only | |
| uv run pytest -m integration # Integration tests only | |
| uv run pytest tests/test_skillbook.py # Specific file | |
| uv run pytest -v # Verbose output | |
| ``` | |
| === "unittest" | |
| ```bash | |
| python -m unittest discover -s tests | |
| python -m unittest discover -s tests -v # Verbose | |
| ``` | |
| ## Testing Without API Calls | |
| Use a mock LLM to test pipeline wiring without making real API calls. Any object with `complete()` and `complete_structured()` methods satisfies the `LLMClientLike` protocol: | |
| ```python | |
| from unittest.mock import MagicMock | |
| from ace import Agent, Reflector, SkillManager | |
| mock_llm = MagicMock() | |
| mock_llm.complete.return_value = '{"reasoning": "test", "final_answer": "4", "skill_ids": []}' | |
| agent = Agent(mock_llm) | |
| reflector = Reflector(mock_llm) | |
| skill_manager = SkillManager(mock_llm) | |
| ``` | |
| ## Unit Testing | |
| ### Testing the Skillbook | |
| ```python | |
| from ace import Skillbook | |
| def test_add_skill(): | |
| skillbook = Skillbook() | |
| skill = skillbook.add_skill( | |
| section="Test", | |
| content="Test strategy", | |
| metadata={"helpful": 0, "harmful": 0, "neutral": 0}, | |
| ) | |
| assert len(skillbook.skills()) == 1 | |
| assert skill.content == "Test strategy" | |
| def test_save_load(tmp_path): | |
| skillbook = Skillbook() | |
| skillbook.add_skill(section="Test", content="Strategy") | |
| path = str(tmp_path / "test.json") | |
| skillbook.save_to_file(path) | |
| loaded = Skillbook.load_from_file(path) | |
| assert len(loaded.skills()) == 1 | |
| ``` | |
| ### Testing the Agent | |
| ```python | |
| from unittest.mock import MagicMock | |
| from ace import Agent, Skillbook | |
| def test_agent_generate(): | |
| mock_llm = MagicMock() | |
| mock_llm.complete.return_value = '{"reasoning": "2+2=4", "final_answer": "4", "skill_ids": []}' | |
| agent = Agent(mock_llm) | |
| output = agent.generate( | |
| question="What is 2+2?", | |
| context="", | |
| skillbook=Skillbook(), | |
| ) | |
| assert output.final_answer is not None | |
| assert output.reasoning is not None | |
| ``` | |
| ### Testing Reflector and SkillManager | |
| ```python | |
| from unittest.mock import MagicMock | |
| from ace import Agent, Reflector, SkillManager, Skillbook | |
| def make_mock_llm(): | |
| mock = MagicMock() | |
| mock.complete.return_value = '{"reasoning": "test", "final_answer": "4", "skill_ids": []}' | |
| return mock | |
| def test_reflector(): | |
| mock_llm = make_mock_llm() | |
| reflector = Reflector(mock_llm) | |
| agent = Agent(mock_llm) | |
| output = agent.generate(question="Test", context="", skillbook=Skillbook()) | |
| reflection = reflector.reflect( | |
| question="Test", | |
| agent_output=output, | |
| skillbook=Skillbook(), | |
| ground_truth="expected", | |
| feedback="Correct", | |
| ) | |
| assert reflection.key_insight is not None | |
| def test_skill_manager(): | |
| sm = SkillManager(make_mock_llm()) | |
| # ... similar pattern with reflection input | |
| ``` | |
| ## Integration Testing | |
| ### End-to-End Learning Cycle | |
| ```python | |
| from unittest.mock import MagicMock | |
| from ace import ( | |
| ACE, Agent, Reflector, SkillManager, | |
| Sample, SimpleEnvironment, | |
| ) | |
| def test_full_learning_cycle(): | |
| mock_llm = MagicMock() | |
| mock_llm.complete.return_value = '{"reasoning": "test", "final_answer": "answer", "skill_ids": []}' | |
| runner = ACE.from_roles( | |
| agent=Agent(mock_llm), | |
| reflector=Reflector(mock_llm), | |
| skill_manager=SkillManager(mock_llm), | |
| environment=SimpleEnvironment(), | |
| ) | |
| samples = [Sample(question="Test", context="", ground_truth="answer")] | |
| results = runner.run(samples, epochs=1) | |
| assert len(results) == 1 | |
| ``` | |
| ### Testing Checkpoints | |
| ```python | |
| def test_checkpoints(tmp_path): | |
| mock_llm = MagicMock() | |
| mock_llm.complete.return_value = '{"reasoning": "test", "final_answer": "A", "skill_ids": []}' | |
| runner = ACE.from_roles( | |
| agent=Agent(mock_llm), | |
| reflector=Reflector(mock_llm), | |
| skill_manager=SkillManager(mock_llm), | |
| environment=SimpleEnvironment(), | |
| checkpoint_dir=str(tmp_path), | |
| checkpoint_interval=1, | |
| ) | |
| samples = [Sample(question="Q", context="", ground_truth="A")] | |
| runner.run(samples, epochs=1) | |
| # Check that checkpoint files were created | |
| checkpoints = list(tmp_path.glob("ace_*.json")) | |
| assert len(checkpoints) > 0 | |
| ``` | |
| ## Common Test Patterns | |
| ### Fixtures | |
| ```python | |
| import pytest | |
| from unittest.mock import MagicMock | |
| from ace import Agent, Reflector, SkillManager, Skillbook | |
| @pytest.fixture | |
| def mock_llm(): | |
| mock = MagicMock() | |
| mock.complete.return_value = '{"reasoning": "test", "final_answer": "4", "skill_ids": []}' | |
| return mock | |
| @pytest.fixture | |
| def skillbook(): | |
| return Skillbook() | |
| @pytest.fixture | |
| def agent(mock_llm): | |
| return Agent(mock_llm) | |
| ``` | |
| ### Mocking LLM Responses | |
| ```python | |
| from unittest.mock import MagicMock | |
| def test_with_mock(): | |
| mock_llm = MagicMock() | |
| mock_llm.complete.return_value = '{"reasoning": "...", "final_answer": "4", "skill_ids": []}' | |
| agent = Agent(mock_llm) | |
| # ... | |
| ``` | |
| ## CI Configuration | |
| ```yaml | |
| # .github/workflows/test.yml | |
| name: Tests | |
| on: [push, pull_request] | |
| jobs: | |
| test: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: astral-sh/setup-uv@v4 | |
| - run: uv sync | |
| - run: uv run pytest -v | |
| ``` | |
| ## Code Quality | |
| ```bash | |
| uv run black ace/ tests/ examples/ # Format | |
| uv run mypy ace/ # Type check | |
| uv run pre-commit run --all-files # All hooks | |
| ``` | |
| ## Troubleshooting | |
| | Problem | Solution | | |
| |---------|----------| | |
| | Import errors | Run `uv sync` to install all dependencies | | |
| | API key errors in tests | Use `MagicMock` for unit tests (see above) | | |
| | Flaky async tests | Increase timeout or use `wait_for_background()` | | |
| | Coverage too low | `--cov-fail-under=25` is the threshold | | |
| ## What to Read Next | |
| - [Full Pipeline Guide](full-pipeline.md) — what you're testing | |
| - [Async Learning](async-learning.md) — testing async pipelines | |