Claude Code testing: unit tests, browser tests, and MCP
Write and run tests, check your app in a browser with MCP, and review what those tests actually prove.
Claude Code can read your project, write tests, run them, and use failures to work out what to change. You can also connect it to a browser through MCP to check how the application behaves.
You do not need an MCP server to start. Claude can run your existing test commands directly. Add browser access or another integration when the task needs it, rather than setting up a collection of tools before writing the first test.
The useful starting point is a behavior you want to check: an expired session must be rejected, a refund must have the right amount, or a failed form submission must preserve what the user typed.
Start with your existing tests
With Claude Code installed, open a session in your repository. Give it a small task before asking it to generate a whole suite:
Read this project's test configuration and a few existing tests.
Tell me how to run them, then run the suite to establish a baseline.
Report any failures or missing setup. Do not change files yet.
Claude should find the runner and commands in the project, not invent a new setup. That might mean Vitest or Jest for JavaScript, pytest for Python, RSpec for Ruby, or the language’s built-in runner. Anthropic’s testing workflow describes using existing tests to guide the framework, style, and assertions.
Check the baseline before continuing. A missing database, unavailable credential, or failing dependency is different from a regression. Ask Claude to say when it could not run something; a test it wrote but never executed is still unverified.
Write unit and integration tests for specific behavior
Choose the kind of test based on what could go wrong:
| What you need to check | Useful test | Example |
|---|---|---|
| A rule or calculation | Unit test | A refund includes the correct tax amount. |
| Components working together | Integration test | A rejected payment does not create an order in the database. |
| A user’s journey through the app | Browser test | A customer can recover from a failed payment and try again. |
For an existing feature, give Claude the expected behavior and ask it to work within the current suite:
Add tests for session expiry. A signed-in customer with an expired
session must not be allowed to check out. A valid session must
still work.
Follow the existing test style. Only change tests, and do not mock
the session check itself. Run the relevant tests, then the full
suite. If the behavior is wrong, show me the failing test before
changing application code.
For an integration test, add the setup constraints. Specify the test database, how fixtures are created, and how they are cleaned up. If the test is meant to verify database persistence, mocking the repository would remove the part you wanted to check. If it touches an external payment provider, use its sandbox or the project’s existing test double, not a live charge.
Expected results should come from a requirement, bug report, or decision you have made. Asking Claude to infer every expectation from the current implementation can produce tests that preserve an existing bug.
Use TDD when changing behavior
For a new feature or bug fix, ask Claude to write and run the test before editing the implementation:
We need to reject sessions at the exact expiry time, not just after it.
Write a regression test using a fixed clock. Run it and show that it
fails because the session is accepted. Do not change the implementation
until we have that failure.
Then ask for the fix:
Make the smallest implementation change that satisfies the test.
Keep the assertion intact. Rerun the regression test and the existing
suite. Explain what changed and flag anything you could not verify.
The first failure matters. An import error does not establish that the test catches the bug. Neither does a test that already passes. Read the failure and check that it describes the behavior you intended to change.
This is also a useful way to limit a task: one failing case, one implementation change, then another run. Anthropic’s best practices emphasize giving Claude an executable check and asking for evidence of the result.

Test the browser with Playwright and MCP
Unit tests cannot tell you whether a submit button is hidden behind a dialog or a customer can complete a journey. For those checks, Claude needs access to the running app.
If your project already uses Playwright, Claude can edit its tests and run npx playwright test through the terminal. MCP is optional. It is useful when you want Claude to interactively open pages, inspect their structure, click controls, and investigate a failure before writing a regression test.
To connect Microsoft’s Playwright MCP server, run this once in your project’s terminal:
claude mcp add --transport stdio playwright -- npx -y @playwright/mcp@latest
This requires Node.js and npm. In a new Claude Code session, use /mcp to check the connection. The -- separates Claude’s configuration options from the server command; Anthropic’s MCP documentation covers scopes, connection status, and permissions.
Start your app with its usual development command, or ask Claude to do that. Then give it the local URL and a bounded browser task:
Use Playwright to check the sign-in form at the local URL I provided.
Try an empty submission and an invalid password using the test account.
Check that each error is visible and that the form can be corrected.
Do not use production accounts or submit real payments.
Show what you observed. Add a Playwright regression test for one useful
case, following this project's setup, and run that saved test.
Exploring the page and saving a test are separate steps. A successful interaction in the conversation does not leave you with a check that will run on the next pull request. Ask for the test file, its assertions, and the command that executed it.

In the saved test, prefer controls located by their accessible names, check visible outcomes, and give each test its own state. Playwright’s testing guidance explains these choices. A test that clicks Submit but never checks the resulting error or success state is incomplete.
Playwright also offers CLI and skills-based browser tools. Its maintainers describe those as a potentially more token-efficient option for coding agents; MCP remains useful for interactive workflows that benefit from persistent browser state. Use the interface that fits your setup, not both by default.
What about other testing MCP servers?
Some integrations handle more of the workflow. TestSprite offers test planning, execution, and results through its MCP integration. Test Collab shows Claude generating and organizing test cases in a test-management system.
Those are different jobs. A written test case is not necessarily an executable automated test. Before adding a service, check what it produces, where the tests run, what data it receives, and whether you can retain and rerun the results. Connect only servers you trust, with access limited to what the task requires.
Keep testing instructions in the project
Once you have a workflow that works, put the recurring details in CLAUDE.md: the real test command, required local services, fixture conventions, and any restrictions on test data. For a project where npm test already runs the suite, a short section could be:
## Testing
- Run the suite with npm test.
- Follow the fixtures and assertion style in nearby tests.
- Use a fixed clock for time-dependent behavior.
- Do not skip failing tests or weaken assertions to get a passing run.
- Report the commands run, results, and any tests you could not execute.
Replace that command with your project’s actual command. Keep the file specific enough to be useful. Claude reads CLAUDE.md as context, not enforced configuration, so important requirements still need checks outside the conversation.
For repeated automation, hooks can run a formatter or another check at defined points in a session. Start with inexpensive checks; running a slow end-to-end suite after every edit usually makes iteration harder. Keep the required regression suite in CI so it runs against the submitted change, regardless of who wrote it.
Review the tests, not just the pass count
A large set of passing tests can still miss an important rule. In Bas Dijkstra’s test-generation experiment, the initial suite looked promising, but mutation testing and further review exposed missed paths and redundant tests. It is one small experiment, not a universal benchmark, but it illustrates why generated tests need review.
Before accepting a change, ask:
- Does the assertion check the behavior we actually want?
- Would a plausible bug make this test fail?
- Are mocks replacing an external dependency, or hiding the behavior under test?
- Is the test independent of the real clock, execution order, and leftover data?
- Did Claude run the saved test and the relevant existing suite?
- Were assertions, snapshots, or test exclusions changed just to get a pass?
For important logic, consider mutation testing: introduce small changes to the implementation and check whether the tests detect them. Inspect surviving mutations; some expose gaps, while others may not change observable behavior. Even a targeted check of one likely bug can tell you more than another batch of nearly identical tests.
Find the remaining coverage gaps with Supercov
Once Claude can run your tests, coverage data can help it choose the next useful one. Supercov reports line, branch, MC/DC, and assertion coverage, with file-level detail the agent can inspect.
For a project whose existing suite runs with npm test, the commands are:
npx supercov -- npm test
npx supercov runs latest
npx supercov runs latest gaps
Everything after -- is your test command. You can ask Claude to run these and use the result:
Measure code coverage with npx supercov. Find one useful MC/DC or
assertion coverage gap and add a focused test for the intended behavior.
Only change tests. Rerun the suite and show the test, its assertion,
and the before-and-after coverage. Report failures instead of changing
application code to make the test pass.
In our JavaScript MC/DC example, line and branch coverage were already 100%, but the tests never checked an expired session. One additional test checked that case and made removing the expiry guard detectable.
That is the use of coverage here: evidence for a specific missing test, not proof that the whole application is correct. The agent workflow guide shows how to repeat the process in your own project.