Test Execution Model
Overview
FirmwareCI test files are structured into stages containing steps. This hierarchical structure enables organized, sequential execution with clear success criteria and failure handling.
Test Structure
Hierarchy
Stages
Stages are named groups of related operations executed sequentially. Each stage contains one or more steps that accomplish a specific testing objective.
Example stages:
- Boot Test: Verify device boots and network connectivity
- Firmware Validation: Run security scans and integrity checks
- Performance Benchmarking: Execute performance tests and collect metrics
- Stress Testing: Apply load and verify stability
Stages execute in definition order. If a step fails within a stage, the stage fails and execution moves to the next stage.
Steps
Steps are individual test operations executed within a stage. FirmwareCI offers a comprehensive set of Test Step Commands ranging from simple bash commands to complex integrations like the Robot Test Framework.
Common step types:
- Command execution: Run shell commands on the DUT
- File operations: Copy files, create archives
- Network operations: Ping devices, check connectivity
- Firmware analysis: Scan with ChipSec, Binarly, FWHunt
- Hardware control: Power cycle, flash firmware, access serial
- Benchmarking: Run CPU tests, measure performance
Steps execute sequentially within their stage. Each step must complete successfully for the next step to begin.
Completion Semantics
FirmwareCI uses strict hierarchical completion logic ensuring test integrity.
Step Completion
A step completes successfully when its underlying command or operation returns a zero exit code. Non-zero exit codes indicate failure.
Success criteria vary by command:
- cmd: Command exits with code 0
- ping: Target responds within timeout
- copy: Files transfer successfully
- chipsec: Scan completes and expectations match
- cpustats: CPU metrics meet defined expectations
Stage Completion
A stage completes successfully only when all constituent steps execute without failure. If any step fails, the stage immediately fails.
Stage failure behavior:
- Mark stage as failed
- Skip remaining steps in the stage
- Continue to next stage
This fail-fast behavior prevents unnecessary execution while allowing subsequent stages to run for diagnostic purposes.
Test Completion
A test completes successfully only when every stage executes without failure. Partial success is not recognized - if any stage fails, the entire test fails.
Test result determination:
- All stages succeed → Test passes
- Any stage fails → Test fails
On-Error Behavior
FirmwareCI provides fine-grained control over how step failures affect test execution through the on-error option.
On-Error Modes
| Mode | Description |
|---|---|
strict | (Default) Stop execution within the stage when a step fails. Remaining steps in the stage are skipped. |
continue | Log the error but continue to the next step. The step is marked as failed, but execution proceeds. |
Inheritance
The on-error value is inherited through a hierarchy, from least to most specific:
- Default:
strict(if nothing is set) - Test Level: Set
on-errorat the top level of the test file - Stage Level: Set
on-errorwithin a stage definition - Step Level: Set
on-errorin the step’soptionsblock
More specific settings override less specific ones. For example, a step-level on-error: continue overrides a test-level on-error: strict.
Important: Pre-stage (Setup) and Post-stage (Teardown) do not inherit from the test-level on-error. They only use their own stage-level or step-level settings.
Failure Propagation
When a step fails, FirmwareCI behavior depends on the on-error setting.
With on-error: strict (Default)
The first failure marks the stage as failed and skips remaining steps in that stage.
With on-error: continue
With on-error: continue, all steps execute regardless of previous failures. The stage and test are still marked as failed, but execution continues.
Cross-Stage Failure
Even though Stage 1 failed, Stage 2 executes. This allows collecting diagnostic information from later stages. The test result is permanently failed regardless of Stage 2’s outcome.
Execution Flow
Standard Flow
- Start: System begins with the first stage in the test file
- Execute steps: Within the stage, steps execute sequentially
- Step success: If all steps succeed, proceed to next stage
- Step failure: If any step fails, skip remaining steps and proceed to next stage
- Continue: Repeat until all stages have been attempted
- Report: Generate test report with pass/fail status
With Pre/Post Stages
Execution order:
- Pre-stage operations (Setup)
- All test stages
- Post-stage operations (Teardown) - always executed, regardless of test outcome
Post-Stage Guaranteed Execution
The Post-stage (Teardown) always executes, even when:
- Any test stage fails
- The Pre-stage fails
- Steps within stages fail
This guarantees proper cleanup and DUT state reset. Use the Post-stage for:
- Powering off the device
- Releasing hardware resources
- Cleaning up temporary files
- Resetting device state
Note: Pre-stage and Post-stage do not inherit on-error from the test level. Configure their error handling explicitly if needed:
Templating
Tests use template variables to access dynamic data:
Input templates: [[input.Binary]] - Data provided when triggering the workflow
Attribute templates: [[attributes.Host]] - DUT-specific configuration
Storage templates: [[storage.tools]] - References to storage items
Secret templates: [[secrets.APIToken]] - Sensitive data from workflow secrets
YAML anchors: Define reusable configuration blocks under defaults keyword
For comprehensive templating syntax, see Templating & Variables.
Next Steps
- Learn to write tests in the Writing Tests guide
- Explore Test File Reference for complete schema
- Review Test Step Commands for available operations


