Skill: F Prime Unit Testing
Step-by-step procedure for writing high-quality unit tests for an
F Prime component. The full reference for scaffolding, assertion
macros, helper functions, TestMain structure, and CMakeLists
registration is in the
unit testing guide.
Follow the guide for implementation details; this skill adds the
workflow order and quality criteria.
0 — Prerequisites
| Item |
Required |
| Component FPP model compiled |
Yes |
Build cache generated (fprime-util generate --ut) |
Yes |
| Component implementation compiles |
Yes |
1 — Scaffold, implement, register, run
- Scaffold:
fprime-util impl --ut — rename .template files,
delete auto-generated *Ac.* / *GTestBase.*.
- Tester class: inherit
<Component>GTestBase, add test methods
and helper functions. See
Tester class structure
and helper functions.
- TestMain:
TEST() macros with COMMENT(...) /
REQUIREMENT(...), seed STest::Random. See
TestMain.
- CMakeLists.txt:
register_fprime_ut(...) with
UT_AUTO_HELPERS and DEPENDS STest. See
CMakeLists.txt registration.
- Build & run:
fprime-util build --ut, fprime-util check,
fprime-util check --coverage.
2 — Key patterns to enforce
clearHistory() at the start of every test action.
component.doDispatch() after every async invocation on
active/queued components.
- Helper functions for all port invocations and assertion groups —
no raw
invoke_to_* + ASSERT_* in test methods.
STest::Pick::any() for port numbers, IDs, sizes where the
specific value does not matter.
3 — Rules-based testing (preferred for complex components)
| Criteria |
Simple tests |
Rules-based |
| Few ports, no state machine |
Preferred |
Overkill |
| Multiple interacting ports |
Possible |
Preferred |
| Stateful behavior (counters, modes) |
Difficult |
Preferred |
| Need random / fuzzing coverage |
Not possible |
Required |
Core constructs (all from TestUtils/RuleBasedTesting.hpp):
FW_RBT_DEFINE_RULE(TesterClass, Group, Rule) — declares a
precondition/action pair and a rule struct on the Tester.
- Shadow state — a Tester member mirroring observable component
state; queried in preconditions, updated in actions.
- Scenarios —
RandomScenario (picks applicable rule at random),
BoundedScenario (wraps another, stops after N steps),
SequenceScenario (fixed order).
Scaffold with fprime-util new --rule-based-test. For file layout,
implementation patterns, and full examples see the
rules-based testing guide
and the Svc/Ccsds/ApidManager exemplar.
Build note: add every Rules/<GroupName>.cpp and
TestState/TestState.cpp to the SOURCES list in CMakeLists.txt
and include DEPENDS STest.
4 — Quality checklist
1---2name: fprime-unit-testing3description: Write F Prime component unit tests. Covers scaffold generation via `fprime-util impl --ut`, the Tester / TestMain / GTestBase pattern, rules-based testing with STest, helper-function design, and the CMakeLists.txt registration. Use whenever creating or extending unit tests for an F Prime component.4---56# Skill: F Prime Unit Testing78Step-by-step procedure for writing high-quality unit tests for an9F Prime component. The full reference for scaffolding, assertion10macros, helper functions, TestMain structure, and CMakeLists11registration is in the12[unit testing guide](https://github.com/nasa/fprime/blob/devel/docs/user-manual/overview/unit-testing.md).13Follow the guide for implementation details; this skill adds the14workflow order and quality criteria.1516---1718## 0 — Prerequisites1920| Item | Required |21|---|---|22| Component FPP model compiled | Yes |23| Build cache generated (`fprime-util generate --ut`) | Yes |24| Component implementation compiles | Yes |2526---2728## 1 — Scaffold, implement, register, run29301. **Scaffold**: `fprime-util impl --ut` — rename `.template` files,31 delete auto-generated `*Ac.*` / `*GTestBase.*`.322. **Tester class**: inherit `<Component>GTestBase`, add test methods33 and helper functions. See34 [Tester class structure](https://github.com/nasa/fprime/blob/devel/docs/user-manual/overview/unit-testing.md#tester-class-structure)35 and [helper functions](https://github.com/nasa/fprime/blob/devel/docs/user-manual/overview/unit-testing.md#helper-functions).363. **TestMain**: `TEST()` macros with `COMMENT(...)` /37 `REQUIREMENT(...)`, seed `STest::Random`. See38 [TestMain](https://github.com/nasa/fprime/blob/devel/docs/user-manual/overview/unit-testing.md#testmain).394. **CMakeLists.txt**: `register_fprime_ut(...)` with40 `UT_AUTO_HELPERS` and `DEPENDS STest`. See41 [CMakeLists.txt registration](https://github.com/nasa/fprime/blob/devel/docs/user-manual/overview/unit-testing.md#cmakeliststxt-registration).425. **Build & run**: `fprime-util build --ut`, `fprime-util check`,43 `fprime-util check --coverage`.4445---4647## 2 — Key patterns to enforce4849- **`clearHistory()`** at the start of every test action.50- **`component.doDispatch()`** after every async invocation on51 active/queued components.52- **Helper functions** for all port invocations and assertion groups —53 no raw `invoke_to_*` + `ASSERT_*` in test methods.54- **`STest::Pick::any()`** for port numbers, IDs, sizes where the55 specific value does not matter.5657---5859## 3 — Rules-based testing (preferred for complex components)6061| Criteria | Simple tests | Rules-based |62|---|---|---|63| Few ports, no state machine | Preferred | Overkill |64| Multiple interacting ports | Possible | **Preferred** |65| Stateful behavior (counters, modes) | Difficult | **Preferred** |66| Need random / fuzzing coverage | Not possible | **Required** |6768**Core constructs** (all from `TestUtils/RuleBasedTesting.hpp`):6970- `FW_RBT_DEFINE_RULE(TesterClass, Group, Rule)` — declares a71 precondition/action pair and a rule struct on the Tester.72- **Shadow state** — a Tester member mirroring observable component73 state; queried in preconditions, updated in actions.74- **Scenarios** — `RandomScenario` (picks applicable rule at random),75 `BoundedScenario` (wraps another, stops after N steps),76 `SequenceScenario` (fixed order).7778Scaffold with `fprime-util new --rule-based-test`. For file layout,79implementation patterns, and full examples see the80[rules-based testing guide](https://github.com/nasa/fprime/blob/devel/docs/how-to/rule-based-testing.md)81and the `Svc/Ccsds/ApidManager` exemplar.8283**Build note:** add every `Rules/<GroupName>.cpp` and84`TestState/TestState.cpp` to the `SOURCES` list in CMakeLists.txt85and include `DEPENDS STest`.8687---8889## 4 — Quality checklist9091- [ ] Every input port has at least one test92- [ ] Every command has nominal + error-path tests93- [ ] Every event asserted (emitted and not-emitted)94- [ ] Every telemetry channel asserted after its update action95- [ ] `clearHistory()` at start of each test action96- [ ] `doDispatch()` after every async invocation on active/queued components97- [ ] Helper functions used — no raw `invoke_to_*` + `ASSERT_*` in test methods98- [ ] `STest::Pick` for port numbers, IDs, sizes where specific value doesn't matter99- [ ] Boundary values tested (min/max buffer size, port index 0 and max)100- [ ] Rules-based testing for stateful / multi-port components (≥ 1000 random steps)101- [ ] No dynamic memory after construction102- [ ] `REQUIREMENT("...")` and `COMMENT("...")` macros present103- [ ] `fprime-util check` passes