2022-09-16 23:41:27 +01:00
""" Tests that gym.make works as expected. """
2023-02-05 00:05:59 +00:00
from __future__ import annotations
2022-06-23 13:54:50 +01:00
import re
2022-08-30 19:47:26 +01:00
import warnings
2022-06-23 13:54:50 +01:00
2022-06-24 22:25:58 +02:00
import numpy as np
2022-06-23 13:54:50 +01:00
import pytest
2022-09-16 23:41:27 +01:00
import gymnasium as gym
2023-02-05 00:05:59 +00:00
from gymnasium . envs . classic_control import CartPoleEnv
2022-09-08 10:11:31 +01:00
from gymnasium . wrappers import (
AutoResetWrapper ,
HumanRendering ,
OrderEnforcing ,
TimeLimit ,
)
2022-09-08 10:10:07 +01:00
from gymnasium . wrappers . env_checker import PassiveEnvChecker
2023-02-05 00:05:59 +00:00
from tests . envs . registration . utils_envs import ArgumentEnv
2022-06-23 13:54:50 +01:00
from tests . envs . utils import all_testing_env_specs
2022-12-05 19:14:56 +00:00
from tests . testing_env import GenericTestEnv , old_step_func
2022-06-23 13:54:50 +01:00
from tests . wrappers . utils import has_wrapper
2023-01-20 14:26:37 +00:00
try :
import shimmy
except ImportError :
shimmy = None
2022-12-01 12:04:57 +00:00
@pytest.fixture ( scope = " function " )
2023-02-05 00:05:59 +00:00
def register_testing_envs ( ) :
2022-12-01 12:04:57 +00:00
""" Registers testing envs for `gym.make` """
gym . register (
id = " test.ArgumentEnv-v0 " ,
2023-02-05 00:05:59 +00:00
entry_point = " tests.envs.registration.utils_envs:ArgumentEnv " ,
2022-12-01 12:04:57 +00:00
kwargs = {
" arg1 " : " arg1 " ,
" arg2 " : " arg2 " ,
} ,
)
2022-06-24 22:25:58 +02:00
2022-12-01 12:04:57 +00:00
gym . register (
id = " test/NoHuman-v0 " ,
2023-02-05 00:05:59 +00:00
entry_point = " tests.envs.registration.utils_envs:NoHuman " ,
2022-12-01 12:04:57 +00:00
)
gym . register (
id = " test/NoHumanOldAPI-v0 " ,
2023-02-05 00:05:59 +00:00
entry_point = " tests.envs.registration.utils_envs:NoHumanOldAPI " ,
2022-12-01 12:04:57 +00:00
)
gym . register (
id = " test/NoHumanNoRGB-v0 " ,
2023-02-05 00:05:59 +00:00
entry_point = " tests.envs.registration.utils_envs:NoHumanNoRGB " ,
2022-12-01 12:04:57 +00:00
)
2022-12-13 18:45:54 +00:00
gym . register (
id = " test/NoRenderModesMetadata-v0 " ,
2023-02-05 00:05:59 +00:00
entry_point = " tests.envs.registration.utils_envs:NoRenderModesMetadata " ,
2022-12-13 18:45:54 +00:00
)
2022-12-01 12:04:57 +00:00
yield
del gym . envs . registration . registry [ " test.ArgumentEnv-v0 " ]
2022-12-13 18:45:54 +00:00
del gym . envs . registration . registry [ " test/NoRenderModesMetadata-v0 " ]
2022-12-01 12:04:57 +00:00
del gym . envs . registration . registry [ " test/NoHuman-v0 " ]
del gym . envs . registration . registry [ " test/NoHumanOldAPI-v0 " ]
del gym . envs . registration . registry [ " test/NoHumanNoRGB-v0 " ]
2022-06-24 22:25:58 +02:00
2022-06-23 13:54:50 +01:00
def test_make ( ) :
2023-02-05 00:05:59 +00:00
""" Test basic `gym.make`. """
env = gym . make ( " CartPole-v1 " )
2022-11-12 10:21:24 +00:00
assert env . spec is not None
2022-06-23 13:54:50 +01:00
assert env . spec . id == " CartPole-v1 "
2023-02-05 00:05:59 +00:00
assert isinstance ( env . unwrapped , CartPoleEnv )
2022-06-23 13:54:50 +01:00
env . close ( )
def test_make_deprecated ( ) :
2023-02-05 00:05:59 +00:00
""" Test make with a deprecated environment (i.e., doesn ' t exist). """
2022-08-30 19:47:26 +01:00
with warnings . catch_warnings ( record = True ) :
with pytest . raises (
2022-09-16 23:41:27 +01:00
gym . error . Error ,
2022-08-30 19:47:26 +01:00
match = re . escape (
" Environment version v0 for `Humanoid` is deprecated. Please use `Humanoid-v4` instead. "
) ,
) :
2023-02-05 00:05:59 +00:00
gym . make ( " Humanoid-v0 " )
2022-06-23 13:54:50 +01:00
2023-02-05 00:05:59 +00:00
def test_make_max_episode_steps ( register_testing_envs ) :
2022-06-23 13:54:50 +01:00
# Default, uses the spec's
2023-02-05 00:05:59 +00:00
env = gym . make ( " CartPole-v1 " )
2022-06-23 13:54:50 +01:00
assert has_wrapper ( env , TimeLimit )
2022-11-12 10:21:24 +00:00
assert env . spec is not None
2023-02-05 00:05:59 +00:00
assert env . spec . max_episode_steps == gym . spec ( " CartPole-v1 " ) . max_episode_steps
2022-06-23 13:54:50 +01:00
env . close ( )
# Custom max episode steps
2023-02-05 00:05:59 +00:00
assert gym . spec ( " CartPole-v1 " ) . max_episode_steps != 100
env = gym . make ( " CartPole-v1 " , max_episode_steps = 100 )
2022-06-23 13:54:50 +01:00
assert has_wrapper ( env , TimeLimit )
2022-11-12 10:21:24 +00:00
assert env . spec is not None
2022-06-23 13:54:50 +01:00
assert env . spec . max_episode_steps == 100
env . close ( )
# Env spec has no max episode steps
2022-09-16 23:41:27 +01:00
assert gym . spec ( " test.ArgumentEnv-v0 " ) . max_episode_steps is None
2023-02-05 00:05:59 +00:00
env = gym . make ( " test.ArgumentEnv-v0 " , arg1 = None , arg2 = None , arg3 = None )
assert env . spec is not None
assert env . spec . max_episode_steps is None
2022-06-23 13:54:50 +01:00
assert has_wrapper ( env , TimeLimit ) is False
env . close ( )
2023-02-05 00:05:59 +00:00
def test_make_autoreset ( ) :
2022-09-16 23:41:27 +01:00
""" Tests that `gym.make` autoreset wrapper is applied only when `gym.make(..., autoreset=True)`. """
2023-02-05 00:05:59 +00:00
env = gym . make ( " CartPole-v1 " )
2022-06-23 13:54:50 +01:00
assert has_wrapper ( env , AutoResetWrapper ) is False
env . close ( )
2023-02-05 00:05:59 +00:00
env = gym . make ( " CartPole-v1 " , autoreset = False )
2022-06-23 13:54:50 +01:00
assert has_wrapper ( env , AutoResetWrapper ) is False
env . close ( )
2022-09-16 23:41:27 +01:00
env = gym . make ( " CartPole-v1 " , autoreset = True )
2022-06-23 13:54:50 +01:00
assert has_wrapper ( env , AutoResetWrapper )
env . close ( )
2023-02-05 00:05:59 +00:00
@pytest.mark.parametrize (
" registration_disabled, make_disabled, if_disabled " ,
[
[ False , False , False ] ,
[ False , True , True ] ,
[ True , False , False ] ,
[ True , True , True ] ,
[ False , None , False ] ,
[ True , None , True ] ,
] ,
)
def test_make_disable_env_checker (
registration_disabled : bool , make_disabled : bool | None , if_disabled : bool
) :
""" Tests that `gym.make` disable env checker is applied only when `gym.make(..., disable_env_checker=False)`.
2022-06-23 13:54:50 +01:00
2023-02-05 00:05:59 +00:00
The ordering is 1. if the ` make ( . . . , disable_env_checker = . . . ) ` is bool , then the ` registration ( . . . , disable_env_checker = . . . ) `
"""
gym . register (
" testing-env-v0 " ,
lambda : GenericTestEnv ( ) ,
disable_env_checker = registration_disabled ,
)
2022-06-23 13:54:50 +01:00
2023-02-05 00:05:59 +00:00
# Test when the registered EnvSpec.disable_env_checker = False
env = gym . make ( " testing-env-v0 " , disable_env_checker = make_disabled )
assert has_wrapper ( env , PassiveEnvChecker ) is not if_disabled
2022-06-23 13:54:50 +01:00
env . close ( )
2023-02-05 00:05:59 +00:00
del gym . registry [ " testing-env-v0 " ]
2022-07-11 02:45:24 +01:00
2023-02-05 00:05:59 +00:00
def test_make_apply_api_compatibility ( ) :
""" Test the API compatibility wrapper. """
2022-09-16 23:41:27 +01:00
gym . register (
2022-09-01 16:02:31 +01:00
" testing-old-env " ,
2022-12-05 19:14:56 +00:00
lambda : GenericTestEnv ( step_func = old_step_func ) ,
2022-09-06 17:20:04 +02:00
apply_api_compatibility = True ,
2022-09-01 16:02:31 +01:00
max_episode_steps = 3 ,
)
2023-02-05 00:05:59 +00:00
# Apply the environment compatibility and check it works as intended
2022-09-16 23:41:27 +01:00
env = gym . make ( " testing-old-env " )
2023-02-05 00:05:59 +00:00
assert isinstance ( env . unwrapped , gym . wrappers . EnvCompatibility )
2022-09-01 16:02:31 +01:00
env . reset ( )
assert len ( env . step ( env . action_space . sample ( ) ) ) == 5
env . step ( env . action_space . sample ( ) )
_ , _ , termination , truncation , _ = env . step ( env . action_space . sample ( ) )
assert termination is False and truncation is True
2023-02-05 00:05:59 +00:00
# Turn off the spec api compatibility
2022-09-16 23:41:27 +01:00
gym . spec ( " testing-old-env " ) . apply_api_compatibility = False
env = gym . make ( " testing-old-env " )
2023-02-05 00:05:59 +00:00
assert isinstance ( env . unwrapped , gym . wrappers . EnvCompatibility ) is False
env . reset ( )
with pytest . raises (
ValueError , match = re . escape ( " not enough values to unpack (expected 5, got 4) " )
) :
env . step ( env . action_space . sample ( ) )
2022-09-01 16:02:31 +01:00
2023-02-05 00:05:59 +00:00
# Apply the environment compatibility and check it works as intended
2022-09-16 23:41:27 +01:00
env = gym . make ( " testing-old-env " , apply_api_compatibility = True )
2023-02-05 00:05:59 +00:00
assert isinstance ( env . unwrapped , gym . wrappers . EnvCompatibility )
2022-09-01 16:02:31 +01:00
env . reset ( )
assert len ( env . step ( env . action_space . sample ( ) ) ) == 5
env . step ( env . action_space . sample ( ) )
_ , _ , termination , truncation , _ = env . step ( env . action_space . sample ( ) )
assert termination is False and truncation is True
2023-02-05 00:05:59 +00:00
del gym . registry [ " testing-old-env " ]
2022-07-11 02:45:24 +01:00
2022-06-23 13:54:50 +01:00
def test_make_order_enforcing ( ) :
2022-09-16 23:41:27 +01:00
""" Checks that gym.make wrappers the environment with the OrderEnforcing wrapper. """
2022-06-23 13:54:50 +01:00
assert all ( spec . order_enforce is True for spec in all_testing_env_specs )
2023-02-05 00:05:59 +00:00
env = gym . make ( " CartPole-v1 " )
2022-06-23 13:54:50 +01:00
assert has_wrapper ( env , OrderEnforcing )
# We can assume that there all other specs will also have the order enforcing
env . close ( )
2022-09-16 23:41:27 +01:00
gym . register (
2022-06-23 13:54:50 +01:00
id = " test.OrderlessArgumentEnv-v0 " ,
2023-02-05 00:05:59 +00:00
entry_point = " tests.envs.registration.utils_envs:ArgumentEnv " ,
2022-06-23 13:54:50 +01:00
order_enforce = False ,
kwargs = { " arg1 " : None , " arg2 " : None , " arg3 " : None } ,
)
2023-02-05 00:05:59 +00:00
env = gym . make ( " test.OrderlessArgumentEnv-v0 " )
2022-06-23 13:54:50 +01:00
assert has_wrapper ( env , OrderEnforcing ) is False
env . close ( )
2023-02-05 00:05:59 +00:00
# There is no `make(..., order_enforcing=...)` so we don't test that
2022-06-23 13:54:50 +01:00
2023-02-05 00:05:59 +00:00
def test_make_render_mode ( ) :
""" Test the `make(..., render_mode=...)`, in particular, if to apply the `RenderCollection` or the `HumanRendering`. """
env = gym . make ( " CartPole-v1 " , render_mode = None )
2022-06-23 13:54:50 +01:00
assert env . render_mode is None
env . close ( )
2023-02-05 00:05:59 +00:00
assert " rgb_array " in env . metadata [ " render_modes " ]
env = gym . make ( " CartPole-v1 " , render_mode = " rgb_array " )
assert env . render_mode == " rgb_array "
env . close ( )
assert " no-render-mode " not in env . metadata [ " render_modes " ]
# cartpole is special that it doesn't check the render_mode passed at initialisation
with pytest . warns (
UserWarning ,
match = re . escape (
" \x1b [33mWARN: The environment is being initialised with render_mode= ' no-render-mode ' that is not in the possible render_modes ([ ' human ' , ' rgb_array ' ]). \x1b [0m "
) ,
) :
env = gym . make ( " CartPole-v1 " , render_mode = " no-render-mode " )
assert env . render_mode == " no-render-mode "
env . close ( )
def test_make_render_collection ( ) :
2022-06-24 22:25:58 +02:00
# Make sure that render_mode is applied correctly
2023-02-05 00:05:59 +00:00
env = gym . make ( " CartPole-v1 " , render_mode = " rgb_array_list " )
assert has_wrapper ( env , gym . wrappers . RenderCollection )
2022-09-01 14:06:42 +01:00
assert env . render_mode == " rgb_array_list "
2023-02-05 00:05:59 +00:00
assert env . unwrapped . render_mode == " rgb_array "
2022-06-24 22:25:58 +02:00
env . reset ( )
renders = env . render ( )
assert isinstance (
renders , list
) # Make sure that the `render` method does what is supposed to
assert isinstance ( renders [ 0 ] , np . ndarray )
env . close ( )
2022-06-23 13:54:50 +01:00
2023-02-05 00:05:59 +00:00
def test_make_human_rendering ( register_testing_envs ) :
2022-06-24 22:25:58 +02:00
# Make sure that native rendering is used when possible
2023-02-05 00:05:59 +00:00
env = gym . make ( " CartPole-v1 " , render_mode = " human " )
2022-06-24 22:25:58 +02:00
assert not has_wrapper ( env , HumanRendering ) # Should use native human-rendering
assert env . render_mode == " human "
env . close ( )
2022-07-01 15:47:10 +02:00
with pytest . warns (
2022-08-30 19:47:26 +01:00
UserWarning ,
2022-07-01 15:47:10 +02:00
match = re . escape (
" You are trying to use ' human ' rendering for an environment that doesn ' t natively support it. The HumanRendering wrapper is being applied to your environment. "
) ,
) :
2023-02-05 00:05:59 +00:00
# Make sure that `HumanRendering` is applied here as the environment doesn't use native rendering
env = gym . make ( " test/NoHuman-v0 " , render_mode = " human " )
2022-07-01 15:47:10 +02:00
assert has_wrapper ( env , HumanRendering )
assert env . render_mode == " human "
env . close ( )
2022-06-24 22:25:58 +02:00
with pytest . raises (
2022-07-01 15:47:10 +02:00
TypeError , match = re . escape ( " got an unexpected keyword argument ' render_mode ' " )
) :
2022-09-16 23:41:27 +01:00
gym . make (
2022-09-01 14:06:42 +01:00
" test/NoHumanOldAPI-v0 " ,
render_mode = " rgb_array_list " ,
2022-07-01 15:47:10 +02:00
)
# Make sure that an additional error is thrown a user tries to use the wrapper on an environment with old API
2022-08-30 19:47:26 +01:00
with warnings . catch_warnings ( record = True ) :
with pytest . raises (
2022-09-16 23:41:27 +01:00
gym . error . Error ,
2022-08-30 19:47:26 +01:00
match = re . escape (
" You passed render_mode= ' human ' although test/NoHumanOldAPI-v0 doesn ' t implement human-rendering natively. "
) ,
) :
2023-02-05 00:05:59 +00:00
gym . make ( " test/NoHumanOldAPI-v0 " , render_mode = " human " )
2022-06-24 22:25:58 +02:00
2022-07-01 15:47:10 +02:00
# This test ensures that the additional exception "Gym tried to apply the HumanRendering wrapper but it looks like
# your environment is using the old rendering API" is *not* triggered by a TypeError that originate from
# a keyword that is not `render_mode`
with pytest . raises (
TypeError ,
match = re . escape ( " got an unexpected keyword argument ' render ' " ) ,
) :
2022-09-16 23:41:27 +01:00
gym . make ( " CarRacing-v2 " , render = " human " )
2022-07-01 15:47:10 +02:00
2022-12-13 18:45:54 +00:00
# This test checks that a user can create an environment without the metadata including the render mode
with pytest . warns (
UserWarning ,
match = re . escape (
2023-01-09 13:12:07 +00:00
" \x1b [33mWARN: The environment is being initialised with render_mode= ' rgb_array ' that is not in the possible render_modes ([]). \x1b [0m "
2022-12-13 18:45:54 +00:00
) ,
) :
gym . make ( " test/NoRenderModesMetadata-v0 " , render_mode = " rgb_array " )
2022-06-23 13:54:50 +01:00
2023-02-05 00:05:59 +00:00
def test_make_kwargs ( register_testing_envs ) :
2022-09-16 23:41:27 +01:00
env = gym . make (
2022-06-23 13:54:50 +01:00
" test.ArgumentEnv-v0 " ,
arg2 = " override_arg2 " ,
arg3 = " override_arg3 " ,
)
2022-11-12 10:21:24 +00:00
assert env . spec is not None
2022-06-23 13:54:50 +01:00
assert env . spec . id == " test.ArgumentEnv-v0 "
2023-02-05 00:05:59 +00:00
assert env . spec . kwargs == {
" arg1 " : " arg1 " ,
" arg2 " : " override_arg2 " ,
" arg3 " : " override_arg3 " ,
}
2022-06-23 13:54:50 +01:00
assert isinstance ( env . unwrapped , ArgumentEnv )
assert env . arg1 == " arg1 "
assert env . arg2 == " override_arg2 "
assert env . arg3 == " override_arg3 "
env . close ( )
2023-02-05 00:05:59 +00:00
def test_import_module_during_make ( ) :
2022-06-23 13:54:50 +01:00
# Test custom environment which is registered at make
2023-02-05 00:05:59 +00:00
assert " RegisterDuringMake-v0 " not in gym . registry
2022-09-16 23:41:27 +01:00
env = gym . make (
2023-02-05 00:05:59 +00:00
" tests.envs.registration.utils_unregistered_env:RegisterDuringMake-v0 "
2022-06-23 13:54:50 +01:00
)
2023-02-05 00:05:59 +00:00
assert " RegisterDuringMake-v0 " in gym . registry
from tests . envs . registration . utils_unregistered_env import RegisterDuringMakeEnv
2022-06-23 13:54:50 +01:00
assert isinstance ( env . unwrapped , RegisterDuringMakeEnv )
env . close ( )
2023-02-05 00:05:59 +00:00
del gym . registry [ " RegisterDuringMake-v0 " ]