Skip to content

Testing Processes

Bernhard Trinnes edited this page Apr 16, 2026 · 1 revision

Testing Processes and Test Plan Template

A test plan turns the practices covered in this workshop into a concrete, repeatable process. This chapter explains what a test plan should contain, why each section exists, and when to write each part. The ready-to-use template is on the Test Plan Template page.


Why a Test Plan Matters

Writing tests without a plan leads to uneven coverage: the easy paths are over-tested, edge cases and error paths are missed, and nobody knows what "done" looks like. A test plan answers three questions before a line of test code is written:

  1. What behaviour needs to be verified?
  2. At which level (unit, component, integration)?
  3. How will the result be assessed?

For embedded systems with hardware dependencies and target-only test execution, a test plan also documents which tests require hardware and how the hardware must be configured, so that running the test suite is repeatable by anyone on the team.


Who Writes the Tests

Testing is not a separate activity handed off after implementation. The developer who writes the code writes the tests for that code.

Test level Who writes the tests When
Unit The developer implementing the class or function Alongside the implementation, before the branch is merged
Component The developer implementing the subsystem Before the branch is merged
Integration The developer implementing the hardware adapter Before the branch is merged; requires target hardware

Rationale: The developer who implements a class knows its intended behaviour, its edge cases, and its failure modes better than anyone else. Separating test authorship from implementation creates a gap where assumptions go untested. Tests written by a different person after the fact tend to test the implementation that exists rather than the contract that was intended.


Definition of Done

No implementation task is complete until its tests are written, passing, and committed. The definition of done for any development ticket that involves business logic is:

  • All business logic classes have unit tests
  • Unit tests cover all documented branches and edge cases
  • Tests build and pass cleanly on the target
  • Integration tests are tagged (*HwIntegration*) and can be filtered in or out
  • No test is skipped without a comment explaining why
  • The test plan (or test plan section) for the ticket is updated

This list is enforced at code review. A pull request that adds business logic without tests is not ready to merge.


CI Gate

All unit and component tests run automatically on every pull request. A failing test blocks the merge.

Developer pushes branch
        │
        ▼
CI runs unit + component tests
        │
   Pass?──── No ──▶  PR blocked; developer fixes tests
        │
       Yes
        │
        ▼
Code review (includes test review)
        │
        ▼
Merge permitted

Integration tests that require hardware are tagged and excluded from the PR gate. They are run manually on the target before a release.

# PR gate: unit and component tests only
ctest --test-dir build --label-exclude HwIntegration

# Pre-release: integration tests only
ctest --test-dir build --label-regex HwIntegration

Development Ticket Template

Every ticket that involves implementation work uses the following template. The quality gates section is mandatory and must be filled in before work begins, not after.


Ticket Template

Title: [Short description of the feature or fix]

Type: Feature / Bug / Refactor

Description

What needs to be built or changed, and why.

Acceptance Criteria

What must be true for this ticket to be considered complete from a product perspective.

  • e.g. The valve opens within 100 ms of pressure falling below the lower threshold
  • e.g. A fault is logged when pressure exceeds the safety limit

Quality Gates

Mandatory. Fill in before starting implementation.

Gate Requirement
Unit tests Which classes require unit tests? List them.
Branch coverage All branches in business logic classes covered
Integration tests Which hardware interactions require integration tests? List them, or "none".
CI All unit and component tests must pass on the PR
Code review Tests reviewed alongside production code

Definition of Done

  • Implementation complete
  • Unit tests written and passing for all business logic in this ticket
  • Integration tests written and tagged HwIntegration (if applicable)
  • CI green on the pull request
  • Code review approved (production code and tests reviewed together)
  • Test plan updated if this ticket changes the scope of an existing plan
  • No skipped tests without a documented reason

Test Notes

Any specific test scenarios, edge cases, or boundary values the reviewer should look for.


The Components of a Test Plan

1. Document Header

Tracks ownership and version history. In a codebase under version control the test plan is a committed document, so changes are traceable. The header records who is responsible for the plan and which software version it covers.

Fields: title, component or module name, author, date, version, status (draft / reviewed / approved).

2. Scope

States explicitly what is and is not covered by this plan. Scope prevents the plan from growing unbounded and makes clear when a gap is intentional rather than an oversight.

Include: which classes, modules, or subsystems are tested. Exclude: what is covered by another plan or is outside the current testing effort.

3. Objectives

One or two sentences stating the quality goal of the testing effort. The objective gives reviewers a way to judge whether the plan is sufficient. For embedded work a typical objective is: "Verify that all business logic in [component] behaves correctly across its full input range without requiring hardware, and verify that the hardware adapters interact correctly with the target at the integration level."

4. Test Levels

Defines which testing pyramid levels apply to this component and what is expected at each. This section prevents misunderstandings about what counts as a unit test versus an integration test.

Level Scope Dependencies Run on
Unit Single class All faked Target (no hardware state required)
Component Subsystem of classes Key interfaces faked Target
Integration Full stack Real hardware Target with hardware connected

5. Hardware and Environment Requirements

Describes the physical setup needed to run integration tests. This is the section a new team member reads to set up their environment. It covers: which target board, which hardware peripherals, power supply requirements, connection diagrams or port assignments, and any setup commands that must be run before the test suite executes.

Unit and component tests must be runnable with no hardware state required beyond having the target board powered on. This should be stated explicitly.

6. Test Cases

The core of the plan. Each test case covers one behaviour. The format is consistent so cases can be reviewed, tracked, and reported against.

For each test case:

  • ID: unique identifier, e.g. TC-FLOW-001
  • Description: one sentence stating what is being verified
  • Level: unit / component / integration
  • Preconditions: the state the system or test doubles must be in before the test runs
  • Steps: the actions the test performs
  • Expected result: the exact observable outcome that constitutes a pass
  • Hardware required: yes / no, and if yes, what

7. Coverage Goals

States the minimum acceptable coverage for the component. For embedded business logic the goal should be 100% branch coverage of all business logic classes. Hardware adapters are covered by integration tests rather than coverage metrics.

Also states which coverage tool is used and how to run it, so results are reproducible.

8. Pass / Fail Criteria

Defines what constitutes a successful test run for the whole plan. Avoids ambiguity at sign-off time.

Example: "All unit and component tests pass with zero failures. All integration tests pass on the target with the reference hardware configuration. Branch coverage for business logic classes is at or above 100%. No test is marked as skipped without a documented reason."

9. Known Limitations and Exclusions

Documents what the plan does not cover and why. Examples: a vendor library whose internals cannot be observed, a hardware feature not present on the development board, or a scenario that requires a specific failure mode that cannot be safely induced on the target.

10. Revision History

A table of changes to the plan itself. Required when the plan is a reviewed or approved document. Each row records the version, date, author, and a brief description of what changed.


When to Write Each Section

Stage Action
Feature design Write Scope and Objectives
Interface definition Write Test Levels and identify test cases
Implementation Write detailed test cases and implement tests
Code review Review test cases alongside production code
Release Confirm Pass/Fail Criteria are met, update Revision History

The plan is a living document. Test cases are added as the implementation grows, and Known Limitations are updated when gaps are discovered.


Applying the Plan to This Workshop

Each module in this workshop has an implicit test plan. The table below maps the plan components to the workshop content.

Plan component Workshop content
Scope Module README: what is and is not compiled
Test levels Test Architecture Patterns: pyramid, unit vs integration
Hardware requirements Module 03 and 07: hardware tags, --gtest_filter
Test cases Each TEST_F in the module's test file
Coverage goals Business logic classes: 100% branch coverage
Pass/fail criteria All tests pass, integration tests tagged and filterable

See the Test Plan Template for the ready-to-fill Markdown document.

See also: Test Architecture Patterns, Deterministic Testing

Clone this wiki locally