
Salesforce UI tests break because most of them depend on things that change without warning: the page’s internal HTML, generated IDs, load timing and your own org’s setup. Salesforce says so in its developer docs: it “has never guaranteed backward-compatible HTML, CSS, or DOM.” Tests that describe what a user sees, not how the page is built, break far less.
We hear about this a lot on sales calls. Between August and October 2026, about 10 of the Salesforce teams we spoke with named locator maintenance as a top problem, on Selenium, Playwright, Provar and UiPath alike. The causes repeat. Here they are, with a way to spot each one and a fix.
The short answer: three layers move under your tests
A Salesforce UI test sits on three layers. Any of them can move without anyone touching the test.

Salesforce’s layer. Component markup, shadow DOM and generated IDs. It changes with three releases a year, plus patches.
Your org’s layer. Page layouts, fields, picklists, validation rules and permissions. Your admins change it every sprint.
The run itself. Load timing, test data and the user the test logs in as. It changes on every run.
Most broken suites are tied to the first layer, then blamed on the third.
1. Generated IDs change on every page load
Lightning generates many element IDs when the page renders. A field that was input-131 this morning can be input-245 after lunch. Older Aura IDs look like 60:220;a and shift the same way. A locator built on them passes once, then fails with no change to the app.
How to spot it: the failing locator contains a number nobody typed, and the test passes again on a rerun.
Fix: locate elements by what the user sees: the field label, the button name, the role. In Playwright that means getByRole and getByLabel. The Playwright docs advise against CSS and XPath because “the DOM can often change.” Our free locator healer scores any locator for how well it survives Lightning changes.
2. Shadow DOM hides component internals
Lightning web components keep their internals inside a shadow tree. Salesforce’s own advice for Selenium is to “query off the component’s shadowRoot property.” XPath can’t cross that boundary: the Playwright docs say XPath “does not pierce shadow roots.” Visualforce pages and some managed-package screens add a second wall, because they render inside iframes.
How to spot it: the element is on screen, but your test says it doesn’t exist.
Fix: drop XPath for anything inside a component. Use role and label locators, which Playwright runs through open shadow roots by default, or Selenium 4’s getShadowRoot(). For Visualforce, switch into the frame first.
3. Salesforce changes the markup between releases
Salesforce ships three major releases a year: Spring, Summer and Winter. Each can change the inside of standard components. In Summer ’23, Salesforce added a wrapper element inside some base components to prepare for native shadow DOM. It warned that “any implementation that uses CSS combinators will fail,” and said more internal changes would follow in later releases.
How to spot it: many tests fail on the same weekend, on pages nobody touched.
Fix: run your full suite on a preview sandbox before production upgrades. For Spring ’27, preview sandboxes move on January 9, 2027, and production follows over three weekends. Our Salesforce release calendar shows the date for your instance. Avoid CSS combinators like > and +. If your team writes code-based tests, Salesforce’s UTAM page objects are updated by Salesforce when base components change. For what changed in the last release, see what Winter ’27 breaks in Selenium and Playwright suites.
4. Pages load in pieces
A Lightning page renders one component at a time. A button can be on screen before it responds to clicks, and a related list can arrive seconds after the record. Fixed sleeps either wait too little or waste minutes on every run.
How to spot it: the test fails on CI but passes on your laptop, or fails at a different step each time.
Fix: wait for a state, not a time: the spinner gone, the field enabled, the toast shown. Playwright’s actionability checks do part of this for you before every click and fill.
5. Your admins changed the page
Not every break comes from Salesforce. An admin moves a field with Dynamic Forms, renames a label, or adds a required field or a validation rule. The test that typed into “Close Date” now finds nothing, or can’t save. The app works. The test is out of date.
How to spot it: failures line up with a deployment or a sandbox refresh, not a Salesforce release.
Fix: run a short smoke suite after every deployment, so a break shows up next to the change that caused it. Check saved records with SOQL or the API, not only the screen. That tells a broken page apart from a changed one.
6. The test logs in as the wrong person
Most suites log in as a System Administrator. Real users see a different page: fewer fields, other record types, missing buttons. A test can pass as admin and fail for every sales rep, or the other way round.
How to spot it: a test passes for you and fails in UAT, or a user reports a bug your suite should have caught.
Fix: run key tests as the real profiles and permission sets. We wrote more on why multi-user testing beats admin bias.
7. Test data drifts
Sandbox refreshes wipe records. Duplicate rules block a record that an earlier run already created. Two tests edit the same account at once. The page is fine; the data under it isn’t.
How to spot it: errors like “duplicate value found” or “record not found,” often only when tests run in parallel.
Fix: create the data each test needs through the API, give it unique names (a timestamp works) and clean up afterwards. Our post on Salesforce test environment strategy covers sandbox planning.
Which one is breaking your suite?
Symptom | Likely cause | First fix |
|---|---|---|
Locator has a number nobody typed; a rerun passes | Generated IDs | Use label or role locators |
Element is on screen but “not found” | Shadow DOM or iframe | Drop XPath; go through the shadow root or switch frames |
Many tests fail on the same weekend | Salesforce release | Run the suite on a preview sandbox first |
Passes locally, fails on CI | Load timing | Wait for a state, not a fixed time |
Fails right after a deployment | Org change | Smoke suite after every deploy |
Passes as admin, fails in UAT | Wrong user | Run as real profiles |
“Duplicate value found” in parallel runs | Test data | Create unique data per test through the API |
How to write Salesforce UI tests that survive a release
Describe what the user sees: labels, button names, roles. Never generated IDs.
Keep XPath and CSS combinators away from anything inside a Lightning component.
Wait for states, not seconds.
Run as real profiles, not only as admin.
Check the data behind the screen with SOQL or the API.
Run the full suite on a preview sandbox every release, and a smoke suite after every deploy.
Put a number on the fixing you do today. Our regression testing cost calculator counts script-fix hours per release.
Where TestZeus fits
We built TestZeus so Salesforce tests describe intent, not markup. You write a test in plain English or Gherkin, like “click Save on the Opportunity,” and the agent finds the element when the test runs. When you need speed and repeatability, Test Blocks turn a working run into step-by-step Playwright code you can read, and try to self-heal a broken step up to five times. Tests can log in as different profiles and check records with SOQL in the same flow.
It won’t fix messy test data or a skipped preview run. Those are process problems, and the fixes above apply with any tool. If you’re planning the bigger picture, start with our Salesforce test strategy template.
FAQ
Why do my Salesforce Selenium tests fail after every release?
Usually because they rely on internal markup: generated IDs, XPath into components or CSS combinators. Salesforce changes that markup between releases and doesn’t guarantee it stays the same. Locators based on labels and roles survive far better.
Can XPath find elements inside Lightning web components?
Not inside a shadow root. Use CSS or role-based locators that pierce open shadow roots, as Playwright does by default, or Selenium 4’s getShadowRoot().
Should we use UTAM?
UTAM is Salesforce’s page-object model for UI tests. It helps teams that write tests in code, because Salesforce maintains the page objects for its standard components. You still write and maintain page objects for your own custom components.
How often does the Salesforce UI change?
Three major releases a year, Spring, Summer and Winter, plus patches in between. Preview sandboxes get each release weeks before production. That gap is your window to catch breaks.
// Start testing //








