mirror of
https://github.com/NicolasBohn/NexQuant.git
synced 2026-08-06 19:47:44 +00:00
test: add 129 tests for critical untested code (core, CoSTEER, factor_coder, model_coder, qlib pipeline)
This commit is contained in:
@@ -0,0 +1,243 @@
|
||||
"""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)
|
||||
Reference in New Issue
Block a user