mirror of
https://github.com/NicolasBohn/NexQuant.git
synced 2026-07-27 15:37:44 +00:00
244 lines
8.7 KiB
Python
244 lines
8.7 KiB
Python
"""Tests for rdagent.core — the core framework abstractions."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import sys
|
|
from pathlib import Path
|
|
from unittest.mock import MagicMock
|
|
|
|
import pytest
|
|
|
|
PROJECT_ROOT = Path(__file__).parent.parent.parent
|
|
sys.path.insert(0, str(PROJECT_ROOT))
|
|
|
|
|
|
# =============================================================================
|
|
# Feedback base class
|
|
# =============================================================================
|
|
|
|
|
|
class TestFeedback:
|
|
def test_default_is_acceptable_returns_true(self):
|
|
from rdagent.core.evaluation import Feedback
|
|
fb = Feedback()
|
|
assert fb.is_acceptable() is True
|
|
|
|
def test_default_finished_returns_true(self):
|
|
from rdagent.core.evaluation import Feedback
|
|
fb = Feedback()
|
|
assert fb.finished() is True
|
|
|
|
def test_default_bool_is_true(self):
|
|
from rdagent.core.evaluation import Feedback
|
|
fb = Feedback()
|
|
assert bool(fb) is True
|
|
|
|
|
|
# =============================================================================
|
|
# EvoStep dataclass
|
|
# =============================================================================
|
|
|
|
|
|
class TestEvoStep:
|
|
def test_default_construction(self):
|
|
from rdagent.core.evolving_framework import EvoStep
|
|
es = EvoStep(evolvable_subjects="mock_evo")
|
|
assert es.evolvable_subjects == "mock_evo"
|
|
assert es.queried_knowledge is None
|
|
assert es.feedback is None
|
|
|
|
def test_full_construction(self):
|
|
from rdagent.core.evolving_framework import EvoStep, QueriedKnowledge
|
|
qk = QueriedKnowledge()
|
|
es = EvoStep(evolvable_subjects="evo", queried_knowledge=qk, feedback="fb")
|
|
assert es.queried_knowledge is qk
|
|
assert es.feedback == "fb"
|
|
|
|
def test_equality_by_reference(self):
|
|
from rdagent.core.evolving_framework import EvoStep
|
|
es1 = EvoStep(evolvable_subjects="a")
|
|
es2 = EvoStep(evolvable_subjects="a")
|
|
assert es1 == es2
|
|
|
|
|
|
# =============================================================================
|
|
# Scenario base class
|
|
# =============================================================================
|
|
|
|
|
|
class TestScenario:
|
|
def test_source_data_default_returns_empty_string(self):
|
|
from rdagent.core.scenario import Scenario
|
|
|
|
class MinimalScenario(Scenario):
|
|
@property
|
|
def background(self) -> str: return "bg"
|
|
@property
|
|
def rich_style_description(self) -> str: return "rich"
|
|
def get_scenario_all_desc(self, **kwargs) -> str: return "all"
|
|
def get_runtime_environment(self) -> str: return "env"
|
|
|
|
scen = MinimalScenario()
|
|
assert scen.source_data == ""
|
|
|
|
def test_source_data_property_calls_get_source_data_desc(self):
|
|
from rdagent.core.scenario import Scenario
|
|
|
|
class FakeScenario(Scenario):
|
|
@property
|
|
def background(self) -> str: return "bg"
|
|
@property
|
|
def rich_style_description(self) -> str: return "rich"
|
|
def get_scenario_all_desc(self, **kwargs) -> str: return "all"
|
|
def get_runtime_environment(self) -> str: return "env"
|
|
def get_source_data_desc(self, task=None) -> str: return "custom_data"
|
|
|
|
scen = FakeScenario()
|
|
assert scen.source_data == "custom_data"
|
|
|
|
|
|
# =============================================================================
|
|
# EvolvingStrategy base class
|
|
# =============================================================================
|
|
|
|
|
|
class TestEvolvingStrategy:
|
|
def test_init_stores_scenario(self):
|
|
from rdagent.core.evolving_framework import EvolvingStrategy
|
|
|
|
class MinimalStrategy(EvolvingStrategy):
|
|
def evolve_iter(self, evo, queried_knowledge=None, evolving_trace=None):
|
|
yield evo
|
|
|
|
mock_scen = MagicMock()
|
|
es = MinimalStrategy(mock_scen)
|
|
assert es.scen is mock_scen
|
|
|
|
|
|
# =============================================================================
|
|
# IterEvaluator base class
|
|
# =============================================================================
|
|
|
|
|
|
class TestIterEvaluator:
|
|
def test_evaluate_returns_feedback(self):
|
|
from rdagent.core.evaluation import Feedback
|
|
from rdagent.core.evolving_framework import IterEvaluator, EvolvableSubjects
|
|
|
|
class MyFeedback(Feedback):
|
|
pass
|
|
|
|
class MyEvaluator(IterEvaluator):
|
|
def evaluate_iter(self):
|
|
evo = yield MyFeedback()
|
|
yield MyFeedback()
|
|
return MyFeedback()
|
|
|
|
eva = MyEvaluator()
|
|
result = eva.evaluate(EvolvableSubjects())
|
|
assert isinstance(result, MyFeedback)
|
|
|
|
def test_evaluate_iter_send_none_stops(self):
|
|
"""Sending None mid-iteration triggers StopIteration with final feedback."""
|
|
from rdagent.core.evaluation import Feedback
|
|
from rdagent.core.evolving_framework import IterEvaluator
|
|
|
|
class MyEvaluator(IterEvaluator):
|
|
def evaluate_iter(self):
|
|
yield Feedback() # kick-off (none)
|
|
evo_next = yield Feedback() # partial eval
|
|
if evo_next is None:
|
|
return Feedback() # early return
|
|
return Feedback() # normal path
|
|
|
|
eva = MyEvaluator()
|
|
gen = eva.evaluate_iter()
|
|
next(gen) # kick-off → first Feedback
|
|
gen.send("any") # evo gets "any" → second Feedback (evo_next NOT assigned yet)
|
|
with pytest.raises(StopIteration):
|
|
gen.send(None) # evo_next = None → return → StopIteration
|
|
|
|
|
|
# =============================================================================
|
|
# Developer base class
|
|
# =============================================================================
|
|
|
|
|
|
class TestDeveloper:
|
|
def test_develop_raises_not_implemented(self):
|
|
from rdagent.core.developer import Developer
|
|
|
|
class MinimalDeveloper(Developer):
|
|
def develop(self, exp):
|
|
return super().develop(exp)
|
|
|
|
dev = MinimalDeveloper(MagicMock())
|
|
with pytest.raises(NotImplementedError):
|
|
dev.develop(MagicMock())
|
|
|
|
|
|
# =============================================================================
|
|
# Knowledge / QueriedKnowledge
|
|
# =============================================================================
|
|
|
|
|
|
class TestKnowledgeHierarchy:
|
|
def test_knowledge_pass_through(self):
|
|
from rdagent.core.evolving_framework import Knowledge, QueriedKnowledge
|
|
k = Knowledge()
|
|
qk = QueriedKnowledge()
|
|
assert isinstance(k, Knowledge)
|
|
assert isinstance(qk, QueriedKnowledge)
|
|
|
|
|
|
# =============================================================================
|
|
# EvolvingAgent (abstract interface)
|
|
# =============================================================================
|
|
|
|
|
|
class TestEvolvingAgent:
|
|
def test_ragevo_agent_init(self):
|
|
from rdagent.core.evolving_agent import RAGEvoAgent
|
|
mock_strategy = MagicMock()
|
|
mock_rag = MagicMock()
|
|
agent = RAGEvoAgent.__new__(RAGEvoAgent)
|
|
RAGEvoAgent.__init__(agent, max_loop=5, evolving_strategy=mock_strategy, rag=mock_rag)
|
|
assert agent.max_loop == 5
|
|
assert agent.evolving_strategy is mock_strategy
|
|
assert agent.rag is mock_rag
|
|
|
|
def test_ragevo_agent_default_knowledge_flags(self):
|
|
from rdagent.core.evolving_agent import RAGEvoAgent
|
|
agent = RAGEvoAgent.__new__(RAGEvoAgent)
|
|
RAGEvoAgent.__init__(agent, max_loop=3, evolving_strategy=MagicMock(), rag=MagicMock())
|
|
assert agent.with_knowledge is False
|
|
assert agent.knowledge_self_gen is False
|
|
assert agent.enable_filelock is False
|
|
|
|
def test_ragevo_agent_with_knowledge_enabled(self):
|
|
from rdagent.core.evolving_agent import RAGEvoAgent
|
|
agent = RAGEvoAgent.__new__(RAGEvoAgent)
|
|
RAGEvoAgent.__init__(
|
|
agent, max_loop=3, evolving_strategy=MagicMock(), rag=MagicMock(),
|
|
with_knowledge=True, knowledge_self_gen=True,
|
|
enable_filelock=True, filelock_path="/tmp/test.lock",
|
|
)
|
|
assert agent.with_knowledge is True
|
|
assert agent.knowledge_self_gen is True
|
|
assert agent.enable_filelock is True
|
|
assert agent.filelock_path == "/tmp/test.lock"
|
|
|
|
|
|
# =============================================================================
|
|
# EvolvableSubjects clone
|
|
# =============================================================================
|
|
|
|
|
|
class TestEvolvableSubjects:
|
|
def test_clone_produces_deep_copy(self):
|
|
from rdagent.core.evolving_framework import EvolvableSubjects
|
|
es = EvolvableSubjects()
|
|
clone = es.clone()
|
|
assert clone is not es
|
|
assert type(clone) is type(es)
|