QA is where Salesforce delivery quietly loses days. Not in writing the tests — in the setup around them: hand-building records to exercise an edge case, then waiting on a sandbox refresh that resets everything you just built. On one team I attacked both with automation and recovered a 60% improvement in testing efficiency. Here's the approach.
The real cost is test data, not test code
Most flaky or shallow Salesforce tests trace back to data. Engineers under deadline create the minimum viable record, miss the bulk and negative cases, and ship coverage that's green but meaningless. The fix is to make good data the path of least resistance — a reusable test-data factory that knows your schema and relationships.
@isTest
public class TestDataFactory {
// Relationship-aware, bulk-safe builders — one place, reused everywhere.
public static List<Account> accounts(Integer n, Boolean doInsert) {
List<Account> accts = new List<Account>();
for (Integer i = 0; i < n; i++) {
accts.add(new Account(Name = 'Acct ' + i, Risk_Score__c = Math.mod(i, 100)));
}
if (doInsert) insert accts;
return accts;
}
public static List<Case> casesFor(List<Account> accts) {
List<Case> cases = new List<Case>();
for (Account a : accts) cases.add(new Case(AccountId = a.Id, Subject = 'Auto'));
insert cases;
return cases;
}
}
A generation platform layered on top of this produced realistic, volume-scaled datasets for whole sandboxes — not just unit tests — so UAT and performance testing finally ran against data that looked like production.
Coverage isn't a number. It's whether your tests exercise the bulk, negative, and security cases your users will actually hit.
Sandbox refresh: from a day to a command
A fresh sandbox is an empty sandbox: missing config, connected apps, sample data, and the fifty little manual tweaks nobody documented. I wrapped all of it in a Bash framework that runs immediately after a refresh, driven by the Salesforce CLI:
#!/usr/bin/env bash
set -euo pipefail
ORG="$1"
sf project deploy start --target-org "$ORG" # post-refresh metadata
sf apex run --file scripts/seed.apex --target-org "$ORG" # reference + test data
sf org assign permset --name QA_Access --target-org "$ORG"
echo "Sandbox $ORG is ready."
What used to be a half-day of click-ops became one command an engineer could run before lunch and forget about.
What made it stick
- One factory, reused everywhere — no more bespoke setup per test class.
- Idempotent scripts — safe to re-run; the same command always yields the same ready state.
- Owned by the team, not a person — checked into version control and code-reviewed like any other code.
Takeaway
Automating the unglamorous parts of QA pays compounding dividends: faster cycles, deeper coverage, and engineers who spend their time testing logic instead of building fixtures. Start with whichever hurts more — data or environments — and make the good path the easy one.
Want help standing up a Salesforce QA automation framework? Let's talk.