-
Notifications
You must be signed in to change notification settings - Fork 35
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Testing workflow with basic tests (#39)
* Setup pytest * Tests for new api * Tests and updates for utils * Update testing workflow * Update testing workflow * Better env close implementation * Attempt to isolate error * Create a lite test suite which uses less memory
- Loading branch information
Showing
15 changed files
with
467 additions
and
29 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
[pytest] | ||
addopts = --ignore=examples/externals --ignore=evogym/simulator/externals --ignore=evogym/examples/gym_test.py | ||
markers = | ||
lite: mark as part of the lite test suite |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,3 +16,5 @@ PyOpenGL-accelerate==3.1.5 | |
torch==1.10.2 | ||
ttkbootstrap==1.5.1 | ||
typing==3.7.4.3 | ||
pytest | ||
pytest-xdist |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
import gymnasium as gym | ||
import pytest | ||
import warnings | ||
import numpy as np | ||
from itertools import product | ||
|
||
import evogym.envs | ||
from evogym import sample_robot | ||
|
||
LITE_TEST_ENV_NAMES = [ | ||
"Pusher-v0", | ||
"Walker-v0", | ||
"Traverser-v0", | ||
] | ||
|
||
@pytest.mark.lite | ||
@pytest.mark.parametrize( | ||
"render_mode, add_options", | ||
list(product( | ||
["human", "screen"], | ||
[True, False], | ||
)) | ||
) | ||
def test_render_modes(render_mode, add_options): | ||
""" | ||
- Env can render to screen | ||
""" | ||
|
||
body, _ = sample_robot((5, 5)) | ||
if add_options: | ||
env = gym.make("Walker-v0", body=body, render_mode=render_mode, render_options={ | ||
"verbose": False, | ||
"hide_background": False, | ||
"hide_grid": False, | ||
"hide_edges": False, | ||
"hide_voxels": False | ||
}) | ||
else: | ||
env = gym.make("Walker-v0", body=body, render_mode=render_mode) | ||
|
||
# Reset | ||
obs, info = env.reset(seed=None, options=None) | ||
|
||
for i in range(10): | ||
|
||
# Step -- we don't need to render explicitly | ||
action = env.action_space.sample() - 1 | ||
ob, reward, terminated, truncated, info = env.step(action) | ||
|
||
env.close() | ||
|
||
def get_all_env_render_params(): | ||
return [ | ||
env_name if env_name not in LITE_TEST_ENV_NAMES | ||
else pytest.param(env_name, marks=pytest.mark.lite) | ||
for env_name in evogym.BASELINE_ENV_NAMES | ||
] | ||
|
||
@pytest.mark.parametrize("env_name", get_all_env_render_params()) | ||
def test_all_env_render(env_name): | ||
""" | ||
- Env can render to screen | ||
""" | ||
|
||
body, _ = sample_robot((5, 5)) | ||
env = gym.make(env_name, body=body, render_mode="human") | ||
|
||
# Reset | ||
obs, info = env.reset(seed=None, options=None) | ||
|
||
for i in range(10): | ||
|
||
# Step -- we don't need to render explicitly | ||
action = env.action_space.sample() - 1 | ||
ob, reward, terminated, truncated, info = env.step(action) | ||
|
||
env.close() | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
import gymnasium as gym | ||
import pytest | ||
import warnings | ||
|
||
import evogym.envs | ||
from evogym import sample_robot | ||
|
||
LITE_TEST_ENV_NAMES = [ | ||
"Pusher-v0", | ||
"Walker-v0", | ||
"Traverser-v0", | ||
] | ||
|
||
def get_params(): | ||
return [ | ||
env_name if env_name not in LITE_TEST_ENV_NAMES | ||
else pytest.param(env_name, marks=pytest.mark.lite) | ||
for env_name in evogym.BASELINE_ENV_NAMES | ||
] | ||
|
||
@pytest.mark.parametrize("env_name", get_params()) | ||
def test_env_creatable_and_has_correct_api(env_name): | ||
""" | ||
- Env is creatable | ||
- Env steps for the correct number of steps | ||
- Env follows the gym API | ||
""" | ||
|
||
body, _ = sample_robot((5, 5)) | ||
env = gym.make(env_name, body=body) | ||
|
||
target_steps = env.spec.max_episode_steps | ||
assert isinstance(target_steps, int), f"Env {env_name} does not have a max_episode_steps attribute" | ||
|
||
# Reset | ||
obs, info = env.reset(seed=None, options=None) | ||
|
||
# Rollout with random actions | ||
n_steps = 0 | ||
while True: | ||
action = env.action_space.sample() - 1 | ||
ob, reward, terminated, truncated, info = env.step(action) | ||
|
||
n_steps += 1 | ||
|
||
if terminated or truncated: | ||
env.reset(seed=None, options=None) | ||
break | ||
|
||
if n_steps > target_steps: | ||
break | ||
|
||
# Make sure we can still step after resetting | ||
env.step(env.action_space.sample() - 1) | ||
|
||
# Check that the env terminated after the correct number of steps | ||
assert n_steps <= target_steps, f"Env {env_name} terminated after {n_steps} steps, expected at most {target_steps}" | ||
if n_steps < target_steps: | ||
warnings.warn(f"Env {env_name} terminated early after {n_steps} steps, expected {target_steps}") | ||
|
||
env.close() | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
import gymnasium as gym | ||
import pytest | ||
import warnings | ||
import numpy as np | ||
from itertools import product | ||
|
||
import evogym.envs | ||
from evogym import sample_robot | ||
|
||
LITE_TEST_ENV_NAMES = [ | ||
"Pusher-v0", | ||
"Walker-v0", | ||
"Traverser-v0", | ||
] | ||
|
||
def get_params(): | ||
params = product( | ||
evogym.BASELINE_ENV_NAMES, | ||
[None, "img", "rgb_array"], | ||
) | ||
return [ | ||
param if param[0] not in LITE_TEST_ENV_NAMES | ||
else pytest.param(*param, marks=pytest.mark.lite) | ||
for param in params | ||
] | ||
|
||
|
||
@pytest.mark.parametrize("env_name, render_mode", get_params()) | ||
def test_render(env_name, render_mode): | ||
""" | ||
- Env can render to none and to image | ||
""" | ||
|
||
body, _ = sample_robot((5, 5)) | ||
env = gym.make(env_name, body=body, render_mode=render_mode) | ||
|
||
# Reset | ||
obs, info = env.reset(seed=None, options=None) | ||
|
||
for i in range(10): | ||
|
||
# Render | ||
result = env.render() | ||
|
||
if render_mode is None: | ||
# Result should be None | ||
assert result is None, f"Env returned {type(result)} instead of None" | ||
else: | ||
# Check img | ||
assert isinstance(result, np.ndarray), f"Env returned {type(result)} instead of np.ndarray" | ||
x, y, c = result.shape | ||
assert c == 3, f"Env returned image with {c} channels, expected 3" | ||
|
||
# Step | ||
action = env.action_space.sample() - 1 | ||
ob, reward, terminated, truncated, info = env.step(action) | ||
|
||
env.close() |
Oops, something went wrong.