testing.pytest_plugin¶
Pytest plugin for the raccoon sim test harness.
This module is registered as a pytest11 entry point in the raccoon
wheel, so once raccoon is installed in a project’s test environment the
fixtures below are available with no conftest boilerplate.
The three fixtures that matter:
robot: a fully wired instance of the project’s generatedsrc.hardware.robot.Robotclass, backed by the mock HAL.scene: a factory for entering araccoon.testing.sim.use_scene()context. Automatically resolves scene names against the project’s ownscenes/dir first, then raccoon’s bundled scenes.run_step: a sync callable that awaitsstep.run_step(robot)with a timeout. Tests stay sync; no pytest-asyncio dependency.
Typical usage:
from raccoon.step.motion.drive_dsl import drive_forward
from raccoon.testing.sim import pose
def test_drives_30cm(robot, scene, run_step):
scene("empty_table.ftmap", start=(20, 50, 0))
run_step(drive_forward(cm=30), robot)
assert pose().x > 45
Attributes¶
Functions¶
|
The discovered raccoon project (root, raw yml data, derived SimRobotConfig). |
|
A fresh |
|
Instantiate the project's generated Robot class. |
|
Factory that enters a |
|
Sync wrapper that awaits |
|
Bypass interpreter shutdown when the mock bundle is loaded. |
Module Contents¶
- testing.pytest_plugin.ROBOT_IMPORT_PATH = 'src.hardware.robot'¶
- testing.pytest_plugin.ROBOT_CLASS_NAME = 'Robot'¶
- testing.pytest_plugin.project_info() testing._project.ProjectInfo¶
The discovered raccoon project (root, raw yml data, derived SimRobotConfig).
Session-scoped because the project layout doesn’t change during a test run. If your tests aren’t inside a raccoon project, requesting this fixture fails with a clear error.
- testing.pytest_plugin.robot_sim_config(project_info: testing._project.ProjectInfo) testing.sim.SimRobotConfig¶
A fresh
SimRobotConfigderived from the project’s yml.Function-scoped so individual tests can mutate it (e.g. add
line_sensors) without leaking state across tests. Use this as an override hook when a test needs non-default sim geometry.
- testing.pytest_plugin.robot(project_info: testing._project.ProjectInfo) Any¶
Instantiate the project’s generated Robot class.
Skips with a helpful message if the installed raccoon wheel wasn’t built with the mock driver bundle. Uses a fresh instance per test so any mutable state on the Robot (motion history, calibration caches) doesn’t leak between tests.
- testing.pytest_plugin.scene(project_info: testing._project.ProjectInfo, robot_sim_config: testing.sim.SimRobotConfig) collections.abc.Callable[Ellipsis, None]¶
Factory that enters a
use_scenecontext for the current test.Call it once per test:
def test_foo(robot, scene, run_step): scene("empty_table.ftmap", start=(20, 50, 0)) run_step(my_step, robot)
The scene is detached automatically at the end of the test. Calling
scenetwice in one test replaces the previous scene.
- testing.pytest_plugin.run_step() collections.abc.Callable[Ellipsis, Any]¶
Sync wrapper that awaits
step.run_step(robot)with a timeout.Tests stay sync so this plugin doesn’t drag in pytest-asyncio. If you need multiple awaits sharing an event loop, write the test as
async defand use pytest-asyncio yourself —run_stepis the simple path for the common case.
- testing.pytest_plugin.pytest_sessionfinish(session: Any, exitstatus: int) collections.abc.Generator¶
Bypass interpreter shutdown when the mock bundle is loaded.
The pybind11-bound MockPlatform singleton has a destruction-order race with the motor/IMU wrapper destructors that can segfault at interpreter shutdown. This applies whenever raccoon’s C extension is imported — not only when the
robotfixture was used — because the extension initialises global state on import.Passes the real
exitstatustoos._exitso CI still sees failures. Suppress withRACCOON_TESTING_NO_EXIT_SHORTCUT=1to debug.Uses
wrapper=True, tryfirst=Trueso that we are the outermost wrapper and yield first — letting all other hooks (especially the terminal reporter which prints the ERRORS and short-summary sections) complete before we callos._exit(). With the oldtrylast=Truenon-wrapper approach the terminal reporter’s post-yield summary code never ran becauseos._exitkilled the process before it could.