Docs menu
Tests by package
Each package's test files: what kind of test each one is, what it checks, whether it needs ROS, and the command that runs it.
This page lists every test file in the workspaces’ own packages and what it checks. The overview explains the kinds of test. A file marked ROS imports rclpy or the launch system, so it needs both setup files sourced and an isolated ROS domain, as described on Run the tests. Every other file runs with plain pytest.
The counts are test functions in each file at the commits above. A parametrized test runs several times, so pytest reports more. Both cars have the same files, except where a table says otherwise.
Every command below runs from ~/racerbot-ws. For a package with ROS files, set up the terminal first:
source /opt/ros/jazzy/setup.bash
source ~/racerbot-ws/install/setup.bash
export ROS_DOMAIN_ID=79 ROS_AUTOMATIC_DISCOVERY_RANGE=LOCALHOSTgap_follow
python3 -m pytest src/gap_follow/test/ -vThe largest suite after pure_pursuit’s. The unit tests call gap_logic.py directly; the node tests start a real gap_follow_node, publish scans, odometry and /joy, and check the command it publishes on /test_only/drive.
| File | Tests | Kind | Checks |
|---|---|---|---|
test_gap_logic.py |
93 | Unit | Every step of the pipeline: scan cleaning, edge extension, the bubble, gap choice, steering and every speed cap, each against a closed form or invariant |
test_gap_logic_corners.py |
39 | Unit | The swept-path clearance, the arc guard and corner set-up |
test_gap_follow_node.py |
54 | Node, ROS | The real node: the four LB cases, stale inputs, the decision log, and that no test ever drives the real /drive |
test_gap_follow_corners_node.py |
15 | Node, ROS | The arc guard and corner logic wired into the node |
test_gap_follow_speed_shaping_node.py |
14 | Node, ROS | The speed changes from the October 20, 2026 floor runs |
test_gap_follow_intent.py |
25 | Node, ROS | /drive_intent: valid, reports the command that was published, and can never delay or stop the drive command |
test_opponent_tracking.py |
62 | Unit | Moving-car detection, tracking and the follow decision |
test_opponent_awareness_node.py |
9 | Node, ROS | Opponent awareness wired into the node |
test_gap_follow_live_tuning.py |
29 | Unit | Which parameters the dashboard may change live, and the limits it may set them to |
test_speed_overrides.py |
17 | Unit | The coupled speed overrides every mapping launch uses |
test_launch_speed.py |
11 | Configuration, ROS | gap_follow_launch.py’s max_speed:=: accepted values, refused values, and the speeds lowered with it |
test_gap_mirror_parity.py |
4 | Parity, ROS | The simulator’s copy of gap_follow commands what the real node commands |
pure_pursuit
python3 -m pytest src/pure_pursuit/test/ -vThe largest suite. Unsourced, it collects only part of its tests and stops on collection errors, which is the example in Check that every test was collected.
| File | Tests | Kind | Checks |
|---|---|---|---|
test_racing_math.py |
90 | Unit | The pure pursuit geometry, curvature, the speed profile, nearest-point search and opponent geometry |
test_tracking_laws.py |
69 | Unit | All four steering laws: signs, the LQR gain against a Riccati iteration and closed-loop stability, Stanley on a circle, MPC limits and misses |
test_tracking_law_integration.py |
21 | Node, ROS | The steering-law seam in the node: every safety layer still applies whatever law is selected |
test_localization_watchdogs.py |
8 | Node, ROS | The pose watchdogs: a frozen pose and a stale timestamp stop the car; a parked car does not trip them |
test_opponent_integration.py |
46 | Node, ROS | The reactive safety net, opponent detection and overtaking, in the real node |
test_pure_pursuit_intent.py |
17 | Node, ROS | /drive_intent from the race controller |
test_pose_frame.py |
9 | Node, ROS | Which point on the car a pose describes, and the 0.26 m LiDAR-to-rear-axle move |
test_auto_map_race.py |
63 | Unit and node, ROS | The mapping-to-racing handover: lap detection, quality checks, the switch of localizer |
test_seed_start_pose.py |
6 | Node, ROS | Seeding the particle filter at the start pose for a saved-map race |
test_waypoint_recorder_integration.py |
1 | Node, ROS | The waypoint recorder’s status messages |
test_recorded_path.py |
30 | Unit | Turning a recorded SLAM lap into a drivable racing line |
test_raceline_optimizer.py |
27 | Unit | The minimum-curvature optimizer, including a circular track whose answer is the outer wall |
test_map_despeckle.py |
18 | Unit | Removing stray returns from saved maps |
test_pure_pursuit_live_tuning.py |
29 | Unit | Which parameters the dashboard may change live |
test_run_commands.py |
9 | Unit | The race commands printed at the end of a mapping run |
drive_intent
python3 -m pytest src/drive_intent/test/ -vPure Python, so it runs on any computer: 95 tests in under a second.
| File | Tests | Kind | Checks |
|---|---|---|---|
test_predict.py |
22 | Unit | The predicted path: a straight line along the heading, a quarter circle that lands where geometry says |
test_schema.py |
42 | Unit | The /drive_intent JSON format: what a payload must contain, its version, and the fields the browser draws |
test_throttle.py |
14 | Unit | The publish-rate limit and the failure latch that turns intent off after repeated errors |
imu_bridge
python3 -m pytest src/imu_bridge/test/ -v| File | Tests | Kind | Checks |
|---|---|---|---|
test_convert.py |
34 | Unit | Units, the mount rotation into car axes, calibration, startup bias and covariances |
test_vehicle_state.py |
49 | Unit | The fused speed and the measured steering angle, and the configuration checks that refuse bad values |
test_gyro_odometry.py |
31 | Unit | Gyro odometry: pose composition, angle wrapping, the heading sources and their fallback |
test_imu_health.py |
15 | Unit | The /imu/status verdict: startup bias, the gravity check, all-zero and stale data |
test_vehicle_state_config.py |
6 | Configuration | vehicle_state.yaml against the code that reads it |
test_imu_status_node.py |
5 | Node, ROS | The node publishes /imu/status the way neural_racer reads it |
neural_racer
python3 -m pytest src/neural_racer/test/ -v| File | Tests | Kind | Checks |
|---|---|---|---|
test_observation.py |
20 | Unit | The observation: scan pooling, the log encoding, history at the start of a run |
test_policy_numpy.py |
15 | Unit | The NumPy network: matches a reference implementation step by step, outputs stay in range for any input |
test_safety_wrapper.py |
17 | Unit | Every wrapper step, and that it never raises the network’s speed |
test_preview.py |
12 | Unit | Map-mode geometry |
test_model_store.py |
12 | Unit | Model loading and approval: hashes, the manifest, refusals |
test_config.py |
3 | Configuration | The shipped neural_racer.yaml |
test_latency.py |
2 | Performance | One tick under 5 ms at the 99th percentile. Meaningful only on the Jetson. |
test_neural_racer_node.py |
22 | Node, ROS | The real node: deadman, shadow mode, refusals, stops and intent |
odom_calibration
python3 -m pytest src/odom_calibration/test/ -vPure Python, apart from five files that run the wizard’s JavaScript and need Node.js installed.
| File | Tests | Kind | Checks |
|---|---|---|---|
test_calibration_math.py |
15 | Unit | Speed-gain calibration from tape-measured runs, forward and reverse |
test_steering_math.py |
31 | Unit | Steering calibration geometry: the arc that produced a measured drift |
test_steering_curve.py |
35 | Unit | The multi-setting circle calibration used on October 16, 2026 |
test_steering_chain.py |
11 | Unit | The reach and centre checks |
test_active_samples.py |
13 | Unit | The October 6, 2026 “gain 0.0” bug and the filter that fixes it |
test_vesc_yaml.py |
21 | Configuration | Writing vesc.yaml: only the requested values change, in the right block |
test_teleop_yaml.py |
12 | Configuration | Writing joy_teleop.yaml: only the full-stick steering scale may change |
test_clamp_and_writes.py |
15 | Unit | Which new values may be written, and the servo clamp check |
test_overrides.py |
22 | Unit | Values typed on the page, the servo-limit step, undo |
test_modes_and_progress.py |
12 | Unit | The wizard’s modes and progress |
test_session_store.py |
4 | Unit | Saving a session |
test_wizard_actions.py |
14 | Unit | What the wizard may write, and how it follows the car |
test_wizard_apply.py, test_wizard_circles.py, test_wizard_overrides.py, test_wizard_steps.py, test_wizard_ui.py |
1 each | Front end | The wizard’s JavaScript, run in Node.js with the page and the HTTP calls faked |
race_diagnostics
python3 -m pytest src/race_diagnostics/test/ -v| File | Tests | Kind | Checks |
|---|---|---|---|
test_run_events.py |
18 | Unit | Classifying log lines into events, and which stop reason wins |
test_node_logs.py |
10 | Unit | Finding and merging ROS’s own per-node log files for a run |
test_run_metadata.py |
14 | Unit | What a run records about the code it ran: git state, uncommitted edits |
test_summarize_run.py |
6 | Unit | summarize_run’s report |
test_record_run_topics.py |
6 | Configuration | Which topics record_run.py records by default |
racerbot_doctor
python3 -m pytest src/racerbot_doctor/test/ -vOnly test_live.py needs ROS. The rest fake the operating system’s files, so they can describe an unplugged VESC or a missing kernel driver without one.
| File | Tests | Kind | Checks |
|---|---|---|---|
test_checks.py |
70 | Unit | Every verdict: a healthy car passes, an unplugged VESC fails at USB and blocks everything above it, a wrong kernel driver is not reported as unplugged |
test_system.py |
17 | Unit | Reading /sys, /proc, /dev and ip: USB IDs, drivers, device nodes |
test_snapshot.py |
7 | Unit | The result types and the layer-by-layer ladder |
test_cli.py |
16 | Unit | Exit codes and printed fixes, and that the doctor never opens a device or publishes |
test_live.py |
6 | Node, ROS | Sampling topics and reading the static transforms |
The LiDAR and camera checks differ between the cars, and so do the corresponding tests.
racerbot_launch
python3 -m pytest src/racerbot_launch/test/ -vThis is the suite to run after any change to a car profile, a shared configuration file or a launch file, together with src/racerbot_car/test/. A failure in the hardware guard means the change overwrote one of a car’s own settings: fix the change, not the test.
| File | Tests | Kind | Checks |
|---|---|---|---|
test_car_profiles.py |
Hardware guard | Both cars’ LiDAR, camera, IMU wiring, steering calibration and limits, and dashboard settings, against each car’s profile and docs/car1-vs-car2.md, whichever car runs it |
|
test_steering_limits_fit_servo.py |
6 | Configuration | Every steering limit fits inside the servo range in vesc.yaml, and the planner plans below the controller’s limit |
test_drive_path_wiring.py |
5 | Configuration | Every bringup wires ackermann_mux’s output into ackermann_to_vesc, in the real launch files and the simulator’s |
test_map_course.py |
13 | Unit | The map_course wrapper: which run folder it reports |
test_map_course_imu.py |
13 | Configuration, ROS | map_course’s imu:= and fused_speed:= wiring, and that fused_speed:=true without the IMU refuses to start |
test_web_dashboard_rb1_config.py (car 1), test_web_dashboard_rb2_config.py (car 2) |
10 | Configuration | The dashboard settings against the parameters the node declares and the bringup transforms |
racerbot_sim
python3 -m pytest src/racerbot_sim/test/ -v| File | Tests | Kind | Checks |
|---|---|---|---|
test_hardware_guard.py |
8 | Unit | The interlock that stops the simulator when any real driver appears on the graph |
test_sim_bridge.py |
17 | Unit | The scripted opponent and the dead-reckoned odometry |
test_tracks.py |
8 | Unit | The generated tracks close a lap and are large enough. Needs Pillow. |
test_harness_procs.py |
5 | Unit | The validation harness cleans up its processes |
racerbot_wiimote_driver
python3 -m pytest src/racerbot_wiimote/racerbot_wiimote_driver/test/ -v| File | Tests | Kind | Checks |
|---|---|---|---|
test_wiimote_connect.py |
10 | Unit | wiimote_connect against a fake bluetoothctl: reconnecting, pairing a new Wiimote, the instructions when none is found |
Tools
These test the simulators and the analysis and training code in tools/, not anything that runs on the car.
| Suite | Files | Checks |
|---|---|---|
tools/f1tenth_sim/tests/ |
5 | The promotion rule for steering laws, track import, that the harness steers with the selected law, and that the Gym’s own collision response never moves a car |
tools/run_analysis/tests/ |
4 | The run analyzer’s actuation measurements, log replay, scan motion, and the IMU report (ROS for the last) |
tools/neural_racer/tests/ |
7 | Training: the GPU simulator against the CPU referee, the exported network against the car’s, the observation and wrapper against the car’s code, release selection |
python3 -m pytest tools/f1tenth_sim/tests/ -vVendored packages
f1tenth_system carries its upstream projects’ own tests: flake8, pep257 and copyright checks, plus joy_teleop’s ROS tests. They test upstream code, and colcon test runs them with everything else.
Checked against
car 1 commit 0265263
and
car 2 commit b81b291, before the two workspaces merged.