Why the FlowTest Metadata Type Brings TDD to Declarative Automation
As enterprises migrate business logic from Apex Triggers into Record-Triggered Flows (Flow), maintaining regression test coverage without writing brittle Apex wrapper tests becomes critical.
Introduced in API v55.0 (and significantly expanded in API v66.0–v67.0), FlowTest (flowTests/<FlowApiName>_<TestName>.flowtest-meta.xml) lets admins and developers version-control declarative Flow unit tests with input mock payloads (TriggeringRecord) and multi-condition assertions (assertions).
Key Metadata Fields on FlowTest
| Field | Type | Required | Description |
|---|---|---|---|
flowApiName |
string |
Yes | Developer name of the target Flow. |
label |
string |
Yes | Display name of the Flow Test in Flow Builder. |
description |
string |
No | Explains the business scenario and expected outcome being verified. |
testPoints |
FlowTestPoint[] |
No | Contains the Start test point (elementApiName: Start with input parameters) and Finish test point (elementApiName: Finish with assertions). |
testPoints.assertions |
FlowTestAssertion[] |
No | List of assertion conditions (leftValueReference, operator, rightValue) and custom errorMessage shown when an assertion fails. |
flowTestDataSources |
FlowTestDataSource[] |
No | (API v66.0+) External/Apex test data provider (dataSourceType: ApexClass). |
Real-World XML Example (flowTests/Case_Priority_Triage_Verify_Enterprise_Escalation.flowtest-meta.xml)
<?xml version="1.0" encoding="UTF-8"?>
<FlowTest xmlns="http://soap.sforce.com/2006/04/metadata">
<description>Verifies that a Case created with Origin Phone and Severity Critical sets Priority to High.</description>
<flowApiName>Case_Priority_Triage</flowApiName>
<label>Verify Enterprise Escalation</label>
<testPoints>
<elementApiName>Start</elementApiName>
<parameters>
<leftValueReference>$Record</leftValueReference>
<type>InputTriggeringRecordInitial</type>
<value>
<sobjectValue>{"Origin":"Phone","Subject":"Production Outage","Status":"New"}</sobjectValue>
</value>
</parameters>
</testPoints>
<testPoints>
<assertions>
<conditions>
<leftValueReference>$Record.Priority</leftValueReference>
<operator>EqualTo</operator>
<rightValue>
<stringValue>High</stringValue>
</rightValue>
</conditions>
<errorMessage>Expected Case Priority to be automatically elevated to High for Phone outages.</errorMessage>
</assertions>
<elementApiName>Finish</elementApiName>
</testPoints>
</FlowTest>Senior Architect Best Practices & Gotchas
Warning
Avoid Hardcoded Record IDs Inside sobjectValue JSON: When a FlowTest is created in Flow Builder using “Select a record from the org,” Flow Builder serializes the sandbox record’s Id, OwnerId, and lookup IDs into <sobjectValue>. Before committing a .flowtest-meta.xml file to Git, strip org-specific 18-character IDs from <sobjectValue> so the test passes in every Scratch Org and Sandbox!
- Assert Both Positive Paths and Custom Error Elements: Using the
HasErroroperator (added in API v64.0), you can write aFlowTestthat specifically verifies your Flow’s Custom Error element blocks invalid record saves just like a Validation Rule test!
Frequently asked questions
Which types of Flows support the FlowTest metadata type?
FlowTest supports Record-Triggered Flows, Autolaunched (No Trigger) Flows, and Data Cloud-Triggered Flows, allowing you to assert variable values, path execution, and custom error outcomes without writing Apex test classes.
How are FlowTest files named in SFDX source format?
In force-app/main/default/flowTests/, each file is named using the pattern FlowApiName_TestDeveloperName.flowtest-meta.xml, such as Account_Before_Save_Sync_Verify_Enterprise_Tier.flowtest-meta.xml.
Do FlowTest executions commit test record changes to the database?
No. Just like Apex unit tests, a FlowTest executes inside a rollback transaction (unless configured otherwise in internal test harnesses), evaluating all assertions at the Finish testPoint and rolling back database changes.
What new FlowTest capabilities were added in API versions 66.0 and 67.0?
API version 66.0 added flowTestDataSources (supporting ApexClass data providers), isolatedObjectExternalKeys, and flowTestFlowVersions for Autolaunched Flows, while API version 67.0 added relative Date comparison operators like IsToday, LastNumberOfDays, and NextNumberOfDays.
Comments
Questions, corrections and tips are welcome. Comments are GitHub Discussions, so you sign in with GitHub.