Docs menu
Testing
What kinds of tests the workspaces have, what each package's tests check, how to run them safely and read their output, and the standard every test is held to.
The workspaces’ own packages hold about 1,600 test functions, plus about 140 more for the tools in tools/. Parametrized tests run once per case, so pytest collects more than that. The two cars’ suites are the same apart from two files in racerbot_launch that guard each car’s own hardware settings.
Every test is a Python function whose name starts with test_. pytest finds those functions, runs each one, and reports whether its assert statements held. A test passes when every assertion holds and fails when one does not.
Kinds of test
The tests fall into a few kinds. A package usually has more than one.
| Kind | What it does | Needs ROS | Example |
|---|---|---|---|
| Unit | Calls one function with chosen inputs and checks the result against something worked out independently: a closed-form answer, an invariant, or a measured value | No | test_racing_math.py checks that a circle of radius comes out with curvature |
| Node | Starts the real ROS node in the test process, publishes fake inputs on its topics, and checks what it publishes | Yes | test_gap_follow_node.py checks that releasing LB publishes speed 0 |
| Configuration | Reads a shipped YAML, launch file or udev rule and checks it against the code that uses it, or against another file it must agree with | Mostly no | test_steering_limits_fit_servo.py checks every steering limit against the servo range in vesc.yaml |
| Hardware guard | Checks that each car’s own hardware settings still match its profile and the hardware reference after any change | Mostly no | test_car_profiles.py: car 1’s USB Hokuyo and car 2’s Ethernet one, each loaded only on its own car |
| Parity | Checks that two copies of the same logic agree: the simulator’s and the node’s, or the training code’s and the car’s | Varies | test_gap_mirror_parity.py: the simulator’s copy of gap_follow commands what the node commands |
| Front end | Runs the calibration wizard’s JavaScript in Node.js with the page and the network faked | No (needs Node.js) | test_wizard_ui.py |
| Performance | Checks that a computation fits its time budget | No | test_latency.py: the neural racer’s tick takes under 5 ms at the 99th percentile on the Jetson |
| Simulator | Drives whole laps in a simulator and judges the result independently of the simulator | Varies | tools/f1tenth_sim/run_validation.py |
| Style | flake8, pep257, copyright headers, in the vendored packages only |
No | test_flake8.py |
Unit tests are the fastest and most precise, so every package with non-trivial mathematics keeps that mathematics in a module that imports no ROS, where unit tests can call it directly. Node tests catch what unit tests cannot: a topic name that is wrong, a parameter that is never read, a deadman check that is never called.
Pages
| Page | Read it for |
|---|---|
| Run the tests | The commands, why tests need their own ROS domain, and how to read the output when something fails |
| Tests by package | What each package’s tests check, and how to run them |
| Test quality standards | The rules for writing a test: prove it can fail, never weaken it to pass |
- Run the testsRun each package's tests on an isolated ROS domain, confirm every test was collected, and read a pass, a collection error and a failure.
- Tests by packageEach package's test files: what kind of test each one is, what it checks, whether it needs ROS, and the command that runs it.
- Test quality standardsThe rules every test in the workspaces follows: prove each test can fail, never weaken a failing test, and the patterns to reject in review.
Checked against
car 1 commit 0265263
and
car 2 commit b81b291, before the two workspaces merged.