diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index f86e4f8e8..45feabdc8 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -57,6 +57,38 @@ jobs: && rm -rf tests/outputs outputs + pytest-minimal: + name: Pytest (minimal install) + runs-on: ubuntu-latest + env: + DATA_DIR: tests/data + MUJOCO_GL: egl + steps: + - uses: actions/checkout@v4 + + - name: Install poetry + run: | + pipx install poetry && poetry config virtualenvs.in-project true + echo "${{ github.workspace }}/.venv/bin" >> $GITHUB_PATH + + - name: Set up Python 3.10 + uses: actions/setup-python@v5 + with: + python-version: "3.10" + + - name: Install poetry dependencies + run: | + poetry install --extras "test" + + - name: Test with pytest + run: | + pytest tests -v --cov=./lerobot --durations=0 \ + -W ignore::DeprecationWarning:imageio_ffmpeg._utils:7 \ + -W ignore::UserWarning:torch.utils.data.dataloader:558 \ + -W ignore::UserWarning:gymnasium.utils.env_checker:247 \ + && rm -rf tests/outputs outputs + + end-to-end: name: End-to-end runs-on: ubuntu-latest diff --git a/tests/test_examples.py b/tests/test_examples.py index c1f3c1dcd..543eb022f 100644 --- a/tests/test_examples.py +++ b/tests/test_examples.py @@ -3,6 +3,8 @@ import subprocess import sys from pathlib import Path +from tests.utils import require_package + def _find_and_replace(text: str, finds_and_replaces: list[tuple[str, str]]) -> str: for f, r in finds_and_replaces: @@ -21,6 +23,7 @@ def test_example_1(): assert Path("outputs/examples/1_load_lerobot_dataset/episode_0.mp4").exists() +@require_package("gym_pusht") def test_examples_3_and_2(): """ Train a model with example 3, check the outputs. diff --git a/tests/utils.py b/tests/utils.py index 6a7066942..74e3ba8f5 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -1,4 +1,5 @@ import platform +from functools import wraps import pytest import torch @@ -61,7 +62,6 @@ def require_env(func): Decorator that skips the test if the required environment package is not installed. As it need 'env_name' in args, it also checks whether it is provided as an argument. """ - from functools import wraps @wraps(func) def wrapper(*args, **kwargs): @@ -82,3 +82,20 @@ def require_env(func): return func(*args, **kwargs) return wrapper + + +def require_package(package_name): + """ + Decorator that skips the test if the specified package is not installed. + """ + + def decorator(func): + @wraps(func) + def wrapper(*args, **kwargs): + if not is_package_available(package_name): + pytest.skip(f"{package_name} not installed") + return func(*args, **kwargs) + + return wrapper + + return decorator