Skip to content
ExponaBLOG
PLAYWRIGHT & BROWSER AUTOMATION · DAY 024 / 100

UI mode for fast feedback: practical tips and trade-offs

Run, watch and debug interactively.

Expona Admin6 min read

Running Playwright in UI mode

When you're building out a suite of browser tests, the feedback loop matters. Waiting for a full test run to complete, then digging through logs to find where things broke, costs time and mental energy. That's where UI mode for fast feedback: practical tips and trade-offs comes in. Playwright's interactive UI mode flips the script—you run tests, watch them execute step by step, and jump between moments in your test timeline to debug in real time.

Start with the simplest invocation:

typescript
npx playwright test --ui

This launches a dedicated UI window that shows your test file tree on the left, a live browser view in the center, and an actions panel on the right. No configuration needed. Your tests run in headed mode (the browser is visible), and you can pause, step through, or rewind at any point. It's closer to debugging in Chrome DevTools than to traditional test running.

You can also open UI mode for a single test file:

typescript
npx playwright test checkout.spec.ts --ui

Or filter by test name:

typescript
npx playwright test --ui -g "should apply discount code"

The trade-off here is speed versus interactivity. UI mode runs one test at a time (or sequentially through filtered tests) rather than in parallel. For development and debugging, that's a win. For CI pipelines, you'll stick with headless runs using npx playwright test without the flag.

Watch mode reruns on save

The real productivity boost emerges when you pair UI mode with watch mode. Add the --debug flag, which keeps the test runner listening for file changes:

typescript
npx playwright test --ui --debug

Now edit your test file, save, and the test reruns automatically in the UI window. You don't restart anything. You make a locator change, save, and immediately see whether the new selector finds your element. This tight loop is invaluable when you're tuning a fragile test or exploring a new feature.

Here's a concrete scenario: you're testing a form with a dynamically generated input ID. Your original test uses page.locator('#user-input-123'), but the ID changes on each load. You switch to a more robust selector in UI mode, save, and the test reruns in under a second. You watch it pass. No terminal, no rebuilding, no restarting the browser.

The watch mode dependency chain works across imports too. If your test imports a helper file (like a login utility), saving that file will also trigger a rerun. This encourages modularizing your test code and sharing fragments across test files.

One caveat: watch mode monitors files in your project root. If you're using a monorepo or non-standard layout, you may need to verify that file watching is picking up your changes. In rare cases, you can trigger a manual rerun by clicking the replay button in the UI.

Time-travel through actions

The timeline feature is where UI mode truly shines for debugging. On the right side of the UI, you'll see a list of every action your test performed: goto, fill, click, screenshot, and so on. Each action is timestamped and expandable.

Click any action in the timeline, and the browser view rewinds to that exact moment. The page state reflects what was on screen after that action completed. You can inspect the DOM, check CSS, or hover to see what was rendered. This is phenomenally faster than adding console logs or screenshots at multiple points in your test.

Example: a multi-step checkout test is failing on the payment page. In UI mode, you click the timeline entry for fill('input[name="cardNumber"]', ...) and see the exact state of the form at that moment. Was the card input visible? Was it enabled? Was the value actually filled? The browser shows you. If something looks wrong, you can hover over elements to see their computed styles, open the DevTools console, and query the DOM.

The browser DevTools are available too. Right-click in the browser pane and select "Inspect" to open DevTools, which will stay synchronized with your test timeline. You're essentially getting a full debugger interface without having to inject breakpoints into your code.

This matters especially for tests that involve animations, lazy loading, or network delays. You can scrub through the timeline to watch the page render in slow motion and pinpoint the exact frame where an element became visible or a class was applied.

Pick locators visually

UI mode includes a locator picker tool that eliminates guesswork when writing selectors. Click the "Pick locator" button (usually a target icon) in the UI toolbar, then hover over elements in the browser. The picker highlights the element and suggests locators in order of reliability:

  • Role-based locators (most robust): page.getByRole('button', { name: 'Submit' })
  • Label or placeholder text: page.getByLabel('Email')
  • Test ID: page.getByTestId('checkout-form')
  • CSS selector (least robust): page.locator('button.primary')

Click a suggestion, and it's inserted into your test file automatically. This takes the friction out of selector maintenance and nudges you toward semantic, accessible locators. Role-based locators are especially valuable because they verify that your UI is actually accessible—if your button doesn't have an accessible role, the picker won't suggest a role-based locator, which is useful feedback.

Let's say you're testing a product page with a complex filter sidebar. Instead of manually building CSS selectors, you open the picker, click the "Apply" button in the filter section, and the UI suggests page.getByRole('button', { name: 'Apply' }). You accept it. Seconds later, your test code updates. If the design team changes the button styling or restructures the DOM, your test still works because it's keyed to the accessible name, not the class list.

The picker also works with chained locators. Hover over nested elements, and you can build up a selector like page.locator('form').getByLabel('Password') by picking each layer. This is far faster than trial-and-error in the test file.

Common mistakes

We've seen teams trip up on a few patterns when using UI mode:

  • Forgetting to exit UI mode before committing. The --ui flag is a development tool. If you accidentally commit a CI config that uses --ui, your pipeline will hang waiting for browser interaction. Always use headless mode in CI.
  • Assuming time-travel is a replacement for assertions. The timeline is a debugging aid, not a test validation tool. You still need explicit assertions in your test code. UI mode shows you what happened; assertions verify that what happened was correct.
  • Ignoring performance implications of watch mode. If you have hundreds of test files, watch mode can become sluggish. For large suites, run UI mode on a subset with -g or by test file.
  • Overrelying on visual picking without understanding the selectors. The picker is a starting point. Review the suggested locators, understand why they work, and refine them if needed. A perfectly generated role-based locator can still be fragile if the underlying HTML structure is poorly organized.
  • Running UI mode on a shared CI machine. UI mode is interactive and requires a display. It's meant for local development. On headless CI agents, you'll need the standard headless test command.

Key takeaways

  • npx playwright test --ui opens an interactive test runner with a live browser, timeline scrubbing, and DevTools integration—perfect for development iteration.
  • Combine UI mode with watch mode (--ui --debug) to rerun tests on file save, creating a tight feedback loop for test writing and locator refinement.
  • The timeline feature lets you jump to any action in your test and inspect the page state at that exact moment, making it faster to spot where tests break than adding logs or screenshots.
  • The visual locator picker suggests accessible, maintainable selectors and inserts them into your test code, reducing time spent on selector engineering.
  • UI mode is a development tool, not a CI tool. Use headless mode (npx playwright test) in pipelines and reserve UI mode for local debugging and test writing.
  • Time-travel and picking are aids to understanding test flow and DOM structure; they don't replace explicit assertions and test logic.
ShareXLinkedInReddit

Found this useful? Support the writing.

Buy me a coffee
Written by
Expona Admin
Site administrator

Comments

Loading comments…

Leave a comment

Comments are reviewed before they appear. Be kind and stay on topic.

Related articles