mjlab/tests/test_task_configs.py
Upstream Snapshot 32a241c28f
Some checks failed
nightly / Test against latest dependencies (py3.10) (push) Has been cancelled
nightly / Test against latest dependencies (py3.13) (push) Has been cancelled
tests / tests (3.13, locked) (push) Has been cancelled
tests / tests (3.13, unlocked) (push) Has been cancelled
tests / pyright (3.10) (push) Has been cancelled
tests / lint-format (push) Has been cancelled
tests / tests (3.10, locked) (push) Has been cancelled
tests / tests (3.11, locked) (push) Has been cancelled
tests / tests (3.12, locked) (push) Has been cancelled
tests / pyright (3.11) (push) Has been cancelled
tests / pyright (3.12) (push) Has been cancelled
tests / pyright (3.13) (push) Has been cancelled
tests / ty-check (3.10) (push) Has been cancelled
tests / ty-check (3.11) (push) Has been cancelled
tests / ty-check (3.12) (push) Has been cancelled
tests / ty-check (3.13) (push) Has been cancelled
tests / stubs (push) Has been cancelled
tests / smoke-test (push) Has been cancelled
Docker / check_paths (push) Has been cancelled
docs / build (push) Has been cancelled
Docker / build (push) Has been cancelled
Import upstream snapshot c19f713c415a699a79d71cd96aa13c3104a05047
Upstream: https://github.com/michaelgillett/mjlab
Upstream-Commit: c19f713c415a699a79d71cd96aa13c3104a05047
Upstream-Branch: main
2026-08-28 15:42:17 +08:00

145 lines
5.1 KiB
Python

"""Generic tests for task config integrity."""
import pytest
from mjlab.envs import ManagerBasedRlEnvCfg
from mjlab.managers.observation_manager import ObservationGroupCfg
from mjlab.tasks.registry import list_tasks, load_env_cfg
@pytest.fixture(scope="module")
def all_task_ids() -> list[str]:
"""Get all registered task IDs."""
return list_tasks()
def test_all_tasks_loadable(all_task_ids: list[str]) -> None:
"""All registered tasks should be loadable without errors."""
for task_id in all_task_ids:
try:
cfg = load_env_cfg(task_id)
assert isinstance(cfg, ManagerBasedRlEnvCfg), (
f"Task {task_id} did not return ManagerBasedRlEnvCfg"
)
except Exception as e:
pytest.fail(f"Failed to load task '{task_id}': {e}")
def test_all_tasks_have_play_config(all_task_ids: list[str]) -> None:
"""All tasks should be loadable in play mode."""
for task_id in all_task_ids:
try:
cfg = load_env_cfg(task_id, play=True)
assert isinstance(cfg, ManagerBasedRlEnvCfg), (
f"Task {task_id} play mode did not return ManagerBasedRlEnvCfg"
)
except Exception as e:
pytest.fail(f"Failed to load task '{task_id}' in play mode: {e}")
def test_play_mode_episode_length(all_task_ids: list[str]) -> None:
"""Play mode tasks should have infinite episode length."""
for task_id in all_task_ids:
cfg = load_env_cfg(task_id, play=True)
assert cfg.episode_length_s >= 1e9, (
f"{task_id} (play mode) episode_length_s={cfg.episode_length_s}, expected >= 1e9"
)
def test_play_mode_observation_corruption_disabled(all_task_ids: list[str]) -> None:
"""Play mode tasks should have observation corruption disabled for policy."""
for task_id in all_task_ids:
cfg = load_env_cfg(task_id, play=True)
assert "actor" in cfg.observations, (
f"Play mode task {task_id} missing 'policy' observation group"
)
policy_obs = cfg.observations["actor"]
assert isinstance(policy_obs, ObservationGroupCfg), (
f"Play mode task {task_id} policy observation is not ObservationGroupCfg"
)
assert not policy_obs.enable_corruption, (
f"Play mode task {task_id} has enable_corruption=True, expected False"
)
def test_training_mode_observation_corruption_enabled(all_task_ids: list[str]) -> None:
"""Training mode tasks should have observation corruption enabled for policy."""
for task_id in all_task_ids:
cfg = load_env_cfg(task_id)
assert "actor" in cfg.observations, (
f"Training task {task_id} missing 'policy' observation group"
)
policy_obs = cfg.observations["actor"]
assert isinstance(policy_obs, ObservationGroupCfg), (
f"Training task {task_id} policy observation is not ObservationGroupCfg"
)
assert policy_obs.enable_corruption, (
f"Training task {task_id} has enable_corruption=False, expected True"
)
def test_critic_observation_corruption_always_disabled(all_task_ids: list[str]) -> None:
"""Critic observations should always have corruption disabled."""
for task_id in all_task_ids:
cfg = load_env_cfg(task_id)
if "critic" not in cfg.observations:
continue
critic_obs = cfg.observations["critic"]
assert isinstance(critic_obs, ObservationGroupCfg), (
f"Task {task_id} critic observation is not ObservationGroupCfg"
)
assert not critic_obs.enable_corruption, (
f"Task {task_id} has critic enable_corruption=True, expected False"
)
def test_play_training_observation_structure_match(all_task_ids: list[str]) -> None:
"""Play and training configs should have matching observation structure."""
for task_id in all_task_ids:
training_cfg = load_env_cfg(task_id)
play_cfg = load_env_cfg(task_id, play=True)
# Same observation groups.
assert set(training_cfg.observations.keys()) == set(play_cfg.observations.keys()), (
f"Observation groups mismatch between {task_id} training and play modes"
)
# Same observation terms within each group.
for obs_group_name in training_cfg.observations:
training_terms = set(training_cfg.observations[obs_group_name].terms.keys())
play_terms = set(play_cfg.observations[obs_group_name].terms.keys())
assert training_terms == play_terms, (
f"Observation terms mismatch in group '{obs_group_name}' "
f"between {task_id} training and play modes"
)
def test_play_training_action_structure_match(all_task_ids: list[str]) -> None:
"""Play and training configs should have matching action structure."""
for task_id in all_task_ids:
training_cfg = load_env_cfg(task_id)
play_cfg = load_env_cfg(task_id, play=True)
assert set(training_cfg.actions.keys()) == set(play_cfg.actions.keys()), (
f"Action structure mismatch between {task_id} training and play modes"
)
def test_play_mode_disables_push_robot(all_task_ids: list[str]) -> None:
"""Play mode tasks should disable push_robot event."""
for task_id in all_task_ids:
cfg = load_env_cfg(task_id, play=True)
assert "push_robot" not in cfg.events, (
f"Play mode task {task_id} has push_robot event, expected it to be removed"
)