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:
- Making code changes
- Forgetting to test all the affected flows
- Pushing code with regressions
- 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:
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('#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:
python test_login.pyIt 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
pip install playwrightplaywright install chromiumStep 2: Ask Claude to write tests
I describe the user flow I want to test, and Claude generates the Playwright script:
"Write a Playwright test that:1. Goes to the signup page2. Fills in email, password, confirm password3. Clicks submit4. 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:
"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:
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
networkidlestate - 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