Every admin knows the rule: Test in a sandbox before it breaks in production. Or as the saying goes, measure twice and cut once. When new or updated solutions are released to your users, you want to be able to predict that they will have the experience you intend. This also goes for ensuring that your flows provide the expected outcomes.
Flow Builder has come a long way in terms of testing — from its early stages to the most recent additions to support testing and debugging, offering a subtle but profound change in how to think about testing. While the familiar debug logs give you insight into how your flow’s logic proceeds down various paths, it can’t always guarantee what the outcome will be. This is what the new Flow features for unit testing provide.
Test for successful outcomes
What if you could also ask, “What happens when the flow gets to a point where it hasn’t thrown any errors, but it has reached the wrong outcome?”
When working with Apex, developers are used to being able to ask these types of questions via unit tests. Unit tests are pieces of code that test if the outcome of the code is what is expected. Unit tests use assertions, which are statements that express what you expect from the code.
Consider a common use case in Apex: Perform an SOQL query to retrieve data, move from record to record within the results, modify certain results, and then save only the updated records to the system. If the Apex runs without error, it lets the developer know that at least there isn’t anything fundamentally wrong. However, unit tests would break this into multiple assertions, like:
- Did we get the records we expected?
- Did we modify the records as expected?
- Did the modified records get updated in the system?
For this exercise, we’re going to look at a very simple flow that’s trying to enforce a rule that if a record has a status of Escalated, the corresponding checkbox should always match. So, we’ll ask questions like:
- Given a particular initial record, does the flow follow the correct decision tree?
- At the end of the decision tree, is the rule being enforced?
Unit testing for your flows
As an admin you’re used to seeing the trusty debug log with (hopefully) the message of a successful flow interview.

Seeing that the flow interview was successful informs you that the flow executed without an error, and that end users are unlikely to see a red banner while trying to use it. However, “success” here really only means that your flow ran, not that it achieved the outcome you expected.
Without the ability to understand whether the outcome is the correct one, you run the risk of a problem that’s harder to detect. Your flow could give the wrong result to your users without any kind of alert or error thrown.
Build the test data
Inherent in the concept of testing for an outcome is building out the situation by modeling data that will mimic the scenario you’re trying to solve. You can now build assertions in Flow just like developers can in Apex. Flow tests are very straightforward: Start with a test record, and assert the outcome or outcomes you expect from the flow.
Let’s say you have a solution for a Check Escalated in Cases flow. The main feature of this flow is:
If the Status is Escalated and the Escalated field isn’t checked, the flow sets the Escalated field to True.
Let’s rewrite that in the form of a question:
If the Status is Escalated, does the record have the Escalated box checked at the end of the flow?
When you go to the flow, you’ll see that new View Test button, which will invite you to create a new test if you haven’t done so — in this case, if you can select an exemplary case or you can create your own example record. First, under the Test Setup tab, you need to determine the source of your data. For now, let’s use Org data.

We’ll save the concept of a data silo for another day. Now, we can use the Next tab to define our triggering record.

When it comes to your test data, variety is key. Remember the core assertion:
If the Status is Escalated and the Escalated field isn’t checked, the flow sets the Escalated field to True.
Break that down into questions that build that assertion:
- Does the record have a status other than Escalated? If so, it should be left alone.
- If a record has a status of Escalated and Escalated is checked, does it finish the flow in that same, correct state?
- If a record has a status of Escalated and Escalated is not checked, does it finish the flow with the updated state?
That’s at least three tests with three different initial records. Of course, there’s a lot of nuance here, but it’s key to creating a robust set of tests.
To go back to the unit test comparison, developers are tasked with creating unit tests that will execute at least 75% lines of their code for production (Salesforce enforces this rule for deployment), and most teams attempt to make that as close to 100% as possible. Why? Because if you add a new conditional loop and don’t test for that loop, you’ve created a blind spot in your coverage that could upset previously established assertions.
To test the assertions, let’s create a record with the status set to Escalated, but the checkbox unchecked. Our flow should check that box.
Use test suites to build assertions
The nice thing is that you don’t have to run one test at a time; rather, if you build out the three we looked at before, you can execute them all at once. When you create a suite of tests, you’re creating a list of assertions, which if true provides a thorough layer of detection for how your flow could go wrong, even when it doesn’t throw an error. Let’s examine an assertion that starts to address our questions above.

Now that we 1) have our sample record to kick off the flow and 2) have created assertions that support our logic, we can track the execution of the flow to see how it performs. Within the “View Tests” modal, now that there are tests, you can select which tests to run, or to run all of them, and then view the details of the outcome.

You can see that it triggered the specific custom error provided by the assertion, letting us know exactly what the incorrect outcome was. Now, instead of a flow potentially giving the wrong answers without error, you can handle the wrong answers within Flow itself.
Here you see that the first assertion passed, but the second one throws an error that the checkbox wasn’t checked. So something in the Set Record portion isn’t working correctly. Without this assertion, the flow would have executed without raising any flags, but now you know exactly where to look for a problem.
Build out regression testing for flows
This is a very, very simple example. As your flow grows and becomes more complex, so should your assertions. Again, this ensures predictability that changes you’ve made to your flow won’t break any of your assertions — and if it does, you can proceed through the path to your custom error message to see exactly what’s going wrong.
By building out your assertions as your flow evolves, there’s an additional benefit: You can test that new changes don’t break existing logic. This is called regression testing, and this practice now also becomes available for Flow.
This raises the importance of adding assertions to your flows moving forward, but also adding coverage to your most commonly used flows at the very least. Once we start to take a broader look at a complicated org with many moving parts, building the confidence that the new functionality won’t break any existing functionality provides a much more reliable deployment from sandbox to production.
Learn more on Trailhead
The example and screenshots come from a Trailhead Playground created for the Flow Debugging module, part of the Flow Implementation I trail. We highly recommend finishing the trail to gain the abilities to confidently build in Flow for your users.
Resources