Files
mcm-26-b/tests/test_hrl_p1.py
T
2026-09-11 21:00:39 +08:00

84 lines
3.0 KiB
Python

"""P1 交付回归:benchmark manifest/真值隔离、纯时间奖励与 project 兼容层。
这些测试不训练神经网络,只验证评测入口和接口契约;重训练属于 smoke 手测。
"""
from __future__ import annotations
import importlib.util
import sys
from pathlib import Path
import pytest
np = pytest.importorskip("numpy")
pytest.importorskip("referee")
from mcm26b.config import ProblemConfig
def _benchmark_module():
path = Path(__file__).parents[1] / "scripts" / "benchmark_hrl.py"
spec = importlib.util.spec_from_file_location("benchmark_hrl_p1", path)
module = importlib.util.module_from_spec(spec)
assert spec.loader is not None
sys.modules[spec.name] = module
try:
spec.loader.exec_module(module)
finally:
pass
return module
def test_manifest_roundtrip_and_truth_summary():
module = _benchmark_module()
manifest = module.make_default_manifest(
problem=3, scenes=2, sources=3, directional=0,
start_seed=123, config=ProblemConfig())
scenes = module.scenes_from_manifest(manifest)
assert [scene.scene_id for scene in scenes] == ["scene-123", "scene-124"]
assert all(scene.truth_channels for scene in scenes)
assert all(1 <= channel <= 20 for scene in scenes
for channel in scene.truth_channels)
def test_benchmark_heuristic_is_valid_and_truth_isolated(tmp_path):
module = _benchmark_module()
manifest = module.make_default_manifest(
problem=3, scenes=1, sources=3, directional=0,
start_seed=777, config=ProblemConfig())
scene = module.scenes_from_manifest(manifest)[0]
run_dir = tmp_path / "run"
result = module.run_scene_variant(
scene, "hrl_heuristic", config=ProblemConfig(), hrl_model=None,
run_dir=run_dir)
row = result["row"]
assert row["valid"] is True
assert row["cleared_count"] == len(scene.truth_channels) == 3
assert row["cleared_matches_truth"] is True
assert row["no_source_declared_absent"] is True
assert (run_dir / "session.jsonl").exists()
# manifest/run summary 中不出现策略可消费的 simulator.sources 真值对象。
assert "sources" not in row
def test_time_only_reward_has_no_per_source_shaping():
from mcm26b.hrl.hierarchical_env import HRLReward
reward = HRLReward.time_only()
assert reward.clear == 0.0
assert reward.detect == 0.0
assert reward.info_weight == 0.0
assert reward.time_scale == 100.0
assert reward.failure >= 3600.0
@pytest.mark.skipif(importlib.util.find_spec("gymnasium") is None,
reason="RL 依赖组未安装")
def test_project_compat_layer_reexports_real_classes():
from mcm26b.hrl.hierarchical_env import HierarchicalEnv
from project.env.local_env import HierarchicalEnv as CompatEnv
from project.env.simulator_client import SimulatorClient
from project.policies.high_level_ppo import HighLevelPolicy
assert CompatEnv is HierarchicalEnv
assert SimulatorClient.__module__ == "mcm26b.protocol.client"
assert HighLevelPolicy.__module__ == "mcm26b.hrl.policy"