Skip to content

Commit

Permalink
Refactor project to be a normal ROS package (#33)
Browse files Browse the repository at this point in the history
* Move to more typical ROS package structure to allow for inclusion in the build process of other packages

* Do not expect a test to fail any more, since ROS was fixed by now

* Update CI to new versions and adapt it to the new layout

* Fix CI

* Debug CI

* More CI debugging

* Fix Sphinx configuration

* Revert debugging attempts

* Cleanup and attempt using CI tools

* debug

* Try without ros-tooling/setup-ros

* Fix installation of packages

* Install dev tools

* Run `rosdep init`

* Update dependency installation

* Fix dependency installation

* Switch from black to ruff

* Try to fix target-ros2-distro argument passing

* Parameterize test

* Ignore CI artifacts in formatting/linting

* Try to repair ruff excludes

* Actually install dependencies

* Fix some paths

* Debug again

* Cleanup

* Link to contributors

* Apply formatting

* Fix tests cases broken after merge

* Slightly better signal handling in with_launch_file

* Remove foxy leftovers

* Cleanup
  • Loading branch information
felixdivo authored May 12, 2024
1 parent 5b954c5 commit 597e617
Show file tree
Hide file tree
Showing 49 changed files with 242 additions and 160 deletions.
8 changes: 3 additions & 5 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,17 @@
"dockerfile": "../Dockerfile",
"context": ".."
},
"settings": {
"terminal.integrated.defaultProfile.linux": "zsh"
},
"customizations": {
"vscode": {
"extensions": [
"ms-python.python",
"redhat.vscode-yaml",
"bungcip.better-toml",
"trond-snekvik.simple-rst",
"GitHub.vscode-github-actions"
"GitHub.vscode-github-actions",
"ms-python.black-formatter"
]
}
},
"postStartCommand": "pip install -e '.[dev,doc]'"
"postStartCommand": "rosdep install --from-paths ros2_easy_test && colcon build --symlink-install && pip install -e './ros2_easy_test[dev,doc]'"
}
35 changes: 23 additions & 12 deletions .github/workflows/python-package.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,41 +13,52 @@ jobs:
strategy:
fail-fast: false # Tests may behave very different across these systems
matrix:
# We do not test on ros:foxy-ros-core, since it causes many problems in the CI pipeline
# TODO: add ros:iron-ros-core when it is available
# We test on all supported LTS versions and the latest rolling release
# TODO: Add `ros:jazzy-ros-core`
container: ["ros:humble-ros-core", "ros:rolling-ros-core"]
container: ${{ matrix.container }}

defaults:
run:
shell: bash
steps:
-
-
name: Checkout repository
uses: actions/checkout@v3
-
name: Install dependencies and the package
name: Install dependencies
run: |
apt-get update -q && apt-get install -qy python3-pip python-is-python3 ros-$ROS_DISTRO-example-interfaces
pip install --upgrade pip setuptools
python -m pip install -e '.[dev]'
apt-get update -q
apt-get install -qy python3-pip python-is-python3 ros-dev-tools
rosdep init
# There seems to be no other way to install the PiPI dependencies:
export PIP_BREAK_SYSTEM_PACKAGES=1
pip install -e './ros2_easy_test[dev]'
- run: echo "ROS_DISTRO=$ROS_DISTRO" >> "$GITHUB_OUTPUT"
id: save_envs
-
uses: ros-tooling/action-ros-ci@v0.3
with:
target-ros2-distro: ${{ steps.save_envs.outputs.ROS_DISTRO }}
package-name: ros2_easy_test
skip-tests: true
-
name: Format (with black)
name: Format (with ruff)
run: |
black --check .
ruff format --check
-
name: Lint (with ruff)
run: |
ruff check .
ruff check
-
name: Type check main code (with mypy)
run: |
mypy ros2_easy_test
mypy ros2_easy_test/ros2_easy_test
-
name: Type check tests (with mypy)
continue-on-error: true # We do not want to fail the build if the type checker fails on the tests
run: |
mypy tests
mypy ros2_easy_test/tests
-
name: Testing (with pytest)
run: |
Expand Down
10 changes: 5 additions & 5 deletions .github/workflows/python-release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ jobs:
- name: Create GitHub Release
uses: softprops/action-gh-release@v1
with:
release_name: Release ${{ github.ref }}
name: Release ${{ github.ref }}
draft: false
prerelease: false

Expand All @@ -32,19 +32,19 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v4
uses: actions/setup-python@v5
with:
python-version: '3.x' # The latest stable version of CPython 3
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install build
- name: Build package
run: python -m build
run: python -m build ros2_easy_test
- name: Publish package
uses: pypa/gh-action-pypi-publish@0bf742be3ebe032c25dd15117957dc15d0cfc38d # Version v1.8.5
uses: pypa/gh-action-pypi-publish@81e9d935c883d0b210363ab89cf05f3894778450 # Version v1.8.14
with:
user: __token__
password: ${{ secrets.PYPI_API_TOKEN }}
60 changes: 60 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -129,3 +129,63 @@ dmypy.json
.pyre/

.ruff_cache

devel/
logs/
build/
bin/
lib/
install/
log/
msg_gen/
srv_gen/
msg/*Action.msg
msg/*ActionFeedback.msg
msg/*ActionGoal.msg
msg/*ActionResult.msg
msg/*Feedback.msg
msg/*Goal.msg
msg/*Result.msg
msg/_*.py
build_isolated/
devel_isolated/

# Generated by dynamic reconfigure
*.cfgc
/cfg/cpp/
/cfg/*.py

# Ignore generated docs
*.dox
*.wikidoc

# eclipse stuff
.project
.cproject

# qcreator stuff
CMakeLists.txt.user

srv/_*.py
*.pcd
*.pyc
qtcreator-*
*.user

/planning/cfg
/planning/docs
/planning/src

*~

# Emacs
.#*

# Catkin custom files
CATKIN_IGNORE

############ CUSTOM ############

# Gets created in the CI pipeline, but we don't want ruff to look at it
ros_ws/build
ros_ws/install
2 changes: 1 addition & 1 deletion .readthedocs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ build:
python:
install:
- method: pip
path: .
path: ros2_easy_test
extra_requirements:
- doc

Expand Down
3 changes: 2 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
FROM ros:humble-ros-core

# Install runtime dependencies
RUN apt-get update -q && apt-get install -qy python3-pip python-is-python3 git zsh ros-$ROS_DISTRO-example-interfaces
RUN apt-get update -q && apt-get install -qy python3-pip python-is-python3 git ros-dev-tools
RUN rosdep init && rosdep update

# Need to have setuptools version 64+ for editable installs
RUN pip install --upgrade pip setuptools
Expand Down
10 changes: 6 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@

[![CI status](https://github.com/felixdivo/ros2-easy-test/actions/workflows/python-package.yaml/badge.svg)](https://github.com/felixdivo/ros2-easy-test/actions/workflows/python-package.yaml)
[![documentation status](https://readthedocs.org/projects/ros2-easy-test/badge/)](https://ros2-easy-test.readthedocs.io/en/latest/)
[![code style](https://img.shields.io/badge/code%20style-black-black)](https://github.com/psf/black)
[![linter](https://img.shields.io/badge/linter-ruff-black)](https://github.com/charliermarsh/ruff)
[![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
[![static type checker](https://img.shields.io/badge/static%20typing-mypy-black)](https://mypy-lang.org/)

A Python test framework for [ROS2](https://ros.org/) allowing for:
Expand Down Expand Up @@ -115,7 +114,10 @@ See [the documentation on that](https://ros2-easy-test.readthedocs.io/en/latest/

## Contributing

You can install the development dependencies with `pip install -e ".[dev]"`. After this, you will have access to the configured formatters `black .` and `ruff check .`.
Basic installation is easiest with the porvided `Dockerfile`.
For the last piece of setup, either open it in the provided [Devcontainer](https://code.visualstudio.com/docs/remote/containers) or maunally run `rosdep install --from-paths ros2_easy_test && colcon build --symlink-install && pip install -e './ros2_easy_test[dev]` afterward.

After this, you will have access to the configured formatter (`ruff format`) and linter (`ruff check`).

You can run the test with simply `pytest`. Coverage reports and timings will be printed on the command line, and a fresh line-by-line coverage report is in `htmlcov/index.html`.

Expand Down Expand Up @@ -143,4 +145,4 @@ See [Releases](https://github.com/felixdivo/ros2-easy-test/releases).
See [LICENSE](LICENSE).

Initially developed by [Felix Divo](https://github.com/felixdivo) at [*Sailing Team Darmstadt e. V.*](https://www.st-darmstadt.de/), a student group devoted to robotic sailing based in Darmstadt, Germany.
Thanks to [Simon Kohaut](https://github.com/simon-kohaut) for his kind and nuanced feedback.
Thanks to [Simon Kohaut](https://github.com/simon-kohaut) for his kind and nuanced feedback, and all [the other awesome contributors](https://github.com/felixdivo/ros2-easy-test/graphs/contributors) for their help and support!
2 changes: 1 addition & 1 deletion doc/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
project = "ROS2 easy-test"

# From: https://stackoverflow.com/a/5872024/3753684
with open(Path(__file__).parents[2] / "ros2_easy_test" / "__init__.py") as init:
with open(Path(__file__).parents[2] / "ros2_easy_test" / "ros2_easy_test" / "__init__.py") as init:
metadata = dict(re.findall('''__([a-z]+)__ = "([^"]+)"''', init.read()))

copyright = f"2021, {metadata['author']}"
Expand Down
64 changes: 6 additions & 58 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,77 +1,25 @@
[build-system]
requires = ["setuptools", "setuptools-scm"]
build-backend = "setuptools.build_meta"

[project]
dynamic = ["version"]
name = "ros2_easy_test"
authors = [
{ name = "Felix Divo", email = "felix.divo@sailingteam.tu-darmstadt.de" },
]
description = "A Python test framework for ROS2 allowing simple and expressive assertions based on message interactions."
readme = "README.md"
requires-python = ">=3.8"
classifiers = [
"Programming Language :: Python :: 3",
"Operating System :: OS Independent",
"Natural Language :: English",
"License :: OSI Approved :: MIT License",
"Intended Audience :: Developers",
"Framework :: Robot Framework :: Library",
"Topic :: Software Development :: Testing",
"Topic :: Software Development :: Testing :: BDD",
"Typing :: Typed",
]
urls = { Homepage = "https://github.com/felixdivo/ros2-easy-test" }
dependencies = [
"makefun>=1.15.2"
]
# The package is discovered automatically (including the py.typed file):
# https://setuptools.pypa.io/en/latest/userguide/package_discovery.html#flat-layout

[project.optional-dependencies]
dev = [
"black~=24.2",
"ruff",
"mypy",
"pytest",
"pytest-cov",
"pytest-sugar",
"hypothesis", # To demonstrate how it works with this
]
doc = [
"sphinx",
"sphinx_rtd_theme",
]

[tool.setuptools.dynamic]
version = { attr = "ros2_easy_test.__version__" }

[tool.pytest.ini_options]
# We want errors to fail loudly to not miss any exceptions in the background
# The latter part shows the duration of the slowest tests
# -v prints the test case names to see deadlocks
addopts = "-Werror --color=yes --cov=ros2_easy_test --doctest-modules --cov-report html --durations=0 --durations-min=3.0 -v"
testpaths = [
"ros2_easy_test", # for the doctests
"tests", # for the actual tests
"ros2_easy_test/ros2_easy_test", # for the doctests
"ros2_easy_test/tests", # for the actual tests
]

[tool.black]
line-length = 110

[tool.isort]
profile = "black"

[tool.ruff]
# Same as Black
line-length = 110
# The lowest supported version
target-version = "py38"
exclude = ["ros_ws/**"] # Gets created by the CI pipeline

[tool.ruff.lint]
select = ["E", "F", "W", "I", "N", "UP"]

[tool.ruff.format]
docstring-code-format = true

[tool.mypy]
warn_return_any = true
warn_unused_configs = true
Expand Down
16 changes: 16 additions & 0 deletions ros2_easy_test/package.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?xml version="1.0"?>
<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
<package format="3">
<name>ros2_easy_test</name>
<version>0.3.0</version>
<description>A Python test framework for ROS2 allowing simple and expressive assertions based on message interactions.</description>
<maintainer email="felix.divo@sailingteam.tu-darmstadt.de">Felix Divo</maintainer>
<license>MIT</license>

<test_depend>python3-pytest</test_depend>
<test_depend>example_interfaces</test_depend>

<export>
<build_type>ament_python</build_type>
</export>
</package>
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"""

__author__ = "Felix Divo <felix.divo@sailingteam.tu-darmstadt.de>"
__version__ = "0.2.0.post1"
__version__ = "0.3.0"

from .decorators import with_launch_file, with_single_node
from .env import ROS2TestEnvironment
Expand Down
Loading

0 comments on commit 597e617

Please sign in to comment.