Files
mcm-26-b/tests/test_hrl_p1.py
2026-09-12 01:56:34 +08:00

87 lines
3.3 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""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
# project 是仓库根部的兼容层:pytest 经 rootdir 把仓库根放进 sys.path,
# 而单独 lint tests/ 时 pylint 的 sys.path 不含仓库根,故此处局部豁免。
# pylint: disable=import-error
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"