New: Choose a Temporary Email or Forwarding Alias for Your Use Case
Tutorials / 2026

2026 Playwright Test Locks: How to Isolate Parallel Email Tests?

Playwright named locks can coordinate tests that compete for the same account or inbox, but they cannot prove that a message belongs to the current test. This guide follows the test timeline, from resource inventory and lock scope to email correlation, retries, cleanup, and the point where isolated inboxes are the better choice.

Playwright runs test files in parallel by default, while tests within a file run sequentially unless you configure them otherwise (Playwright’s parallel testing guide). A named lock can serialize tests that compete for the same shared resource. It cannot prove that a message belongs to the test reading it. Use the lock for resource contention, then add a unique test identifier or an isolated recipient to reduce verification-code mix-ups.

This week: identify the shared resource, confirm the lock API and scope against your installed Playwright version, and add an assertion that ties each email to its test run.

This guide is for developers running Playwright tests across files, workers, or projects; QA engineers checking registration and verification flows; and CI owners deciding whether to lock a shared inbox or create separate test resources.

Last updated October 24, 2026. The guidance below was checked against the Playwright release notes, parallel testing guide, and Test API documentation. Confirm the exact API syntax and availability against your installed version before adopting it.

Before setup: map the resources your tests share

Start by tracing what each test reads and changes. “We use the same test mailbox” is a useful clue, but it does not establish that every intermittent failure comes from parallel execution. A bad email query, a stale message, a delayed delivery, or an incorrect test assertion can produce similar symptoms.

List the resources used by the email flow:

  • Recipient inbox: Do several tests poll the same mailbox or mail-reading endpoint?
  • Test account: Do tests change the same account’s password, verification state, or profile?
  • Mailbox state: Can one test delete, archive, or mark messages as read while another is checking them?
  • Application state: Does registering one test user invalidate another user’s token or verification link?
  • Test execution boundary: Do the competing tests run in one Playwright invocation, or in separate CI jobs or independent runs?

Then name the failure you want to prevent. If tests overwrite or consume shared state, you have a resource-contention problem. If a test reads an old email or another test’s verification message, you also have an email-correlation problem. Those are separate problems and need separate checks.

Testing arrangement What a named lock can coordinate What it does not establish Better fit when
Shared account and shared inbox Access by tests using the same lock, within the lock’s documented scope That the email being read belongs to the current test The shared resource is unavoidable and the test can wait
Separate accounts, shared inbox Access to the inbox if all competing tests use the same lock Which account or run caused a particular message Inbox access itself is destructive or ambiguous
Separate recipient per test No shared inbox access may need coordination That the email content is correct You can create or route mail to isolated recipients
Shared inbox with unique message identifier Resource access, if needed Delivery or application correctness on its own You can assert a run-specific identifier in the message

Treat the table as a diagnosis aid, not a guarantee of product behavior. A lock only coordinates the tests that declare and use it in the scope documented for your installed version. It does not lock a mailbox service against an unrelated process.

During configuration: choose a lock name from the resource

A Playwright named lock should describe the resource being protected, not a broad category such as “email.” Use the same name only for tests that actually contend for the same account, inbox, or mutable state. Give unrelated resources distinct names so they do not block each other.

For example, a shared registration account and a shared notification inbox may need different locks. If a particular test changes both, it must follow the project’s documented locking rules for acquiring both resources. Avoid inventing a lock acquisition pattern: verify the current API and its supported use in the Playwright Test API reference.

The key design question is scope. A lock may be usable at an individual test or a describe group, depending on the API and version. A group-level lock is appropriate only if every test in that group shares the protected resource. Otherwise, you can serialize tests that could safely run concurrently.

Also check whether your test files are configured to run in parallel. The official guide distinguishes parallel execution across files from execution within a file, and documents configuration that changes that behavior. A lock should match the real execution pattern; adding one without confirming which tests overlap can hide the actual source of a failure.

How do you apply a Playwright named lock across files or projects?

Give every test that competes for the same resource the same lock name, even when those tests live in different files. Do not assume that matching names coordinate tests across separate Playwright invocations, CI jobs, or machines. The official documentation for your installed version must confirm the lock’s namespace and execution boundary.

For projects, check whether the projects are part of the same test run and whether the lock documentation says their tests share a lock namespace. If the projects run independently, a Playwright lock may not coordinate them. In that case, use separate accounts or inboxes, or introduce an external coordination mechanism designed for the shared resource. Do not treat a lock name as a distributed lock unless the official documentation explicitly supports that behavior.

A useful review question is: “If these two tests start in different files or projects, will the documented lock implementation make one wait?” Confirm the answer with a focused test in your own project before depending on it in CI.

At execution: serialize only the tests that actually compete

Once the scope is clear, use the lock consistently around the operation that touches the shared resource. A test that polls a shared inbox, changes a shared account, and deletes messages may need protection across the whole critical section—not just around the first inbox read.

The intended behavior is narrow: tests using the same lock should not access the protected resource at the same time, while tests using unrelated resources should remain eligible to run in parallel. This preserves useful concurrency instead of turning the whole email suite into a serial queue.

Use this execution sequence:

  1. Start with a reproducible failure. Run the affected tests with the current parallel settings and capture the test name, account, recipient, and message identifiers.
  2. Add the lock to every contender. Search the test suite for all code paths that read, modify, or clean up the shared resource. A missing contender can still race with the locked tests.
  3. Keep unrelated work outside the critical section. Page setup, pure assertions, and operations on isolated accounts do not need to wait for a shared inbox unless the resource contract requires it.
  4. Run both contention and non-contention cases. Confirm that tests sharing the resource no longer overlap, then check that tests with separate resources still run concurrently.
  5. Record what the lock covers. Document the resource, the tests that use it, and the execution boundary. Revisit the decision when test projects or CI execution are reorganized.

A lock can reduce competing reads and writes. It cannot guarantee that the mail service delivered a message, that a query selected the right message, or that the application generated the expected verification link. Those are separate assertions.

When mail arrives: prove its connection to the current test

Can a Playwright test lock prevent parallel tests from reading the wrong verification code?

Not by itself. The lock can make tests take turns accessing a shared resource when they share the documented lock scope. It does not label a message, filter the inbox, or know which test caused an email to be sent. If an old message is still present, a test can still select it after acquiring the lock.

Add an application-controlled identifier to the test flow. Depending on your product, that could be a unique test account, a recipient assigned to the run, or a non-secret correlation value included in the message body or another field your test can inspect. Then assert that the selected message matches the current test’s expected identifier and state.

Do not use the verification code alone as proof of ownership. A code can be stale, or another test can have triggered a message for the same account. Check the associated account, run identifier, requested action, and current verification state before accepting the code or link.

A lock answers “who can access this shared resource at once?” A correlation assertion answers “does this message belong to my test?” Keep both checks if you need both guarantees.

How can you confirm a shared-inbox email belongs to the current run?

Use evidence produced by your own application and test setup. A robust assertion should connect the message to the intended test account and action, and should reject messages that do not match the current run’s identifier. Where the email reader exposes message metadata, preserve enough of it in failure output to explain why the message matched.

Avoid logging the full verification code, password-reset token, or a complete sensitive message body in CI output. Log the test identifier, recipient alias, message timestamp or message ID when available, and the reason a message was accepted or rejected. That gives you useful diagnostics without turning the test report into a store of secrets or personal data.

Your test should also handle the “no matching message” case explicitly. A timeout or empty result should fail with context about the expected identifier and the inbox query, not silently fall back to the newest email. Selecting the newest message can hide a stale-mail problem rather than solve it.

On rerun: keep retries and cleanup inside the isolation plan

A retry is another execution attempt, not proof that the first attempt’s state disappeared. Playwright documents the testInfo.retry value for distinguishing retry attempts; its initial value is 0, and it increases on subsequent retry iterations (TestInfo API). Use that information to make the attempt visible in logs and, where appropriate, in test data.

The documented default retry count is 0; projects can configure retries, so check the actual configuration instead of assuming a rerun policy (Playwright retry guide). More importantly, a retry can encounter messages left by the earlier attempt. Make your message-selection logic reject mail that does not match the current attempt or run, rather than relying on the inbox being empty.

Review cleanup as a resource operation too:

  • Does cleanup delete only messages created by this test, or can it remove another test’s evidence?
  • Can a cleanup hook run while another test is reading the same mailbox?
  • Does a retry reuse the same account and recipient, or receive a fresh isolated target?
  • Do failure logs distinguish the first attempt from a retry and show why a message was accepted?

If cleanup touches a shared resource, it belongs under the same coordination plan as the test that reads or modifies that resource. If cleanup cannot safely identify which messages it owns, avoid broad deletion and consider isolating the recipient instead.

At acceptance: keep the lock or isolate the mail target

Use this decision path after you have rerun the tests:

  • If failures came from simultaneous access to one shared account or inbox, and the lock prevents that overlap: keep the lock, document its exact scope, and retain the email-correlation assertion.
  • If tests still pick up stale or mismatched messages after access is serialized: add a run-specific identifier or separate recipient. The lock is not the missing email association.
  • If different projects or CI jobs do not share the lock’s documented scope: use separate accounts or recipient targets, or choose coordination that spans those executions.
  • If the test cannot prove which run caused the email: do not accept the latest message as a pass. Improve correlation or redesign the test resource.
  • If a test requires long-lived account recovery, replies, or repeatable access to historical mail: use a dedicated test mailbox or another controlled test target rather than a disposable address.

This is the acceptance boundary: a Playwright named lock can coordinate tests in the same run that declare the same lock, within the scope supported by the installed version. It cannot replace end-to-end mail receipt assertions, guarantee correct delivery, or prove that a verification message belongs to the current test.

For the surrounding test-data policy, see the guide to managing test data through its lifecycle. If you need a temporary recipient for registration tests on your own product, first review the QA email test checklist and confirm that the receiving and retention behavior fits your assertions. Once you know you need to inspect real mail, MaskSend can be one option for keeping test messages out of your work inbox; do not use it for accounts that require reliable long-term recovery or replies. Start from MaskSend and verify the current inbox capabilities and retention details before building them into your test workflow.

Test email delivery now

Use a disposable inbox for short-term sign-ups and an independent forwarding alias for lasting relationships. Save your real email address for communication you trust.

Open temporary email