Skip to content

How to Use Playwright with Claude Code for Automated UI Testing

Problem

When I develop frontend applications, I often forget to manually test after making code changes. This leads to bugs slipping through to production. I wanted a way to automatically run UI tests after each edit, catching regressions before I even see the broken code.

Environment

  • Python 3.8+
  • Playwright (latest)
  • Claude Code
  • Local development server (npm/vite/any)

What happened?

I was building a React application and found myself repeatedly:

  1. Making code changes
  2. Forgetting to test all the affected flows
  3. Pushing code with regressions
  4. Getting bug reports from users

I heard that Claude Code can work with Playwright directly. So I tried asking Claude to enable Playwright in my project.

The setup was straightforward. I asked Claude to write a simple Playwright script to test my login flow:

test_login.py
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch(headless=True)
page = browser.new_page()
# Navigate and wait for JS to execute
page.goto('http://localhost:5173')
page.wait_for_load_state('networkidle')
# Take screenshot for verification
page.screenshot(path='/tmp/landing_page.png', full_page=True)
# Test user flow
page.fill('#email', '[email protected]')
page.fill('#password', 'securepassword')
page.click('button[type="submit"]')
# Verify result
page.wait_for_selector('.dashboard')
assert page.is_visible('.user-profile')
browser.close()

Claude generated this script and I ran it:

Run test script
python test_login.py

It worked. The script navigated to my app, filled in the login form, and verified the dashboard appeared.

How to solve it?

But running tests manually is still a chore. The real value comes from closed-loop testing - having Claude run Playwright tests automatically after each code edit.

Here’s how I set up the workflow:

Step 1: Install Playwright

Terminal window
pip install playwright
playwright install chromium

Step 2: Ask Claude to write tests

I describe the user flow I want to test, and Claude generates the Playwright script:

Prompt to Claude
"Write a Playwright test that:
1. Goes to the signup page
2. Fills in email, password, confirm password
3. Clicks submit
4. Verifies the success message appears"

Step 3: Run tests after each edit

When Claude makes code changes to my frontend, I ask it to also run the relevant Playwright tests:

Prompt to run tests
"After making this change, run test_login.py and show me any failures"

Claude runs the test and shows me if anything broke.

Step 4: Discover elements in dynamic apps

For apps with dynamic content, I use element discovery:

discover_elements.py
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch(headless=True)
page = browser.new_page()
page.goto('http://localhost:5173')
page.wait_for_load_state('networkidle')
# Discover interactive elements
buttons = page.locator('button').all()
links = page.locator('a[href]').all()
inputs = page.locator('input, textarea, select').all()
print(f"Found {len(buttons)} buttons, {len(links)} links, {len(inputs)} inputs")
browser.close()

This helps Claude understand what elements exist before writing tests.

You can see that I succeeded in setting up automated browser testing with minimal effort.

The reason

I think the key reasons this works well:

  • Claude understands Playwright natively - It knows the API and can write correct code
  • Closed-loop prevents regressions - Tests run immediately after changes, catching bugs early
  • No context switching - Claude writes and runs tests, I focus on code
  • Screenshots capture failures - Visual evidence of what went wrong

Common mistakes I made

  • Not waiting for networkidle state - dynamic content wasn’t ready when tests ran
  • Using fragile selectors like div > div > button - they break when markup changes
  • Forgetting browser.close() - left orphan browser processes
  • Running headless=False in CI - caused failures in environments without displays

Summary

In this post, I showed how to use Playwright with Claude Code for automated UI testing. The key point is setting up closed-loop testing where Claude runs Playwright scripts after each code edit, catching regressions before they reach production.

Final Words + More Resources

My intention with this article was to help others share my knowledge and experience. If you want to contact me, you can contact by email: Email me

Here are also the most important links from this article along with some further resources that will help you in this scope:

Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!

Comments