You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[Feature] Locks to avoid concurrent runs of specific tests #21484
Errors due to the concurrent runs is a common issue in test automation.
Currently there is no support for locks to avoid this in playwright and the tests must be run sequential, as far as i can tell.
Usually only a small set of tests will require lock, but the test execution is significant slower sequentially.
It is also not possible to implement them outside playwirght for several reasons:
using a locking mechanism in the test / beforeEach is not possible due to the timeout of the test method
using a fixture with a custom timeout would be an option, but with differen locks i need different fixtures
In both options the workers will be blocked until the lock is aquired and we might end in a deadlock if multiple locks are needed.
Playwirght could support locks on test level by adding options to the test(title, callback) method with a list of named locks.
The excution of the test will be block until no other test is currently using these locks. To avoid deadlocks the usage of locks could be limited to not allow nested locks.
Reacted by Dominik Hirsch, Matthias Günter, Kaoru Shirai, Abraham Schilling, David Cloutier, kendoxeng, mcengel, Camo30, Arnaud Dagnelies, kendoxsta and 25 more
edit: actually they probably wont work since a single failure in the dependency will prevent running the second project.
At that point I'd say its probably best to just run two separate projects and have them write to the same directory for the HTML report if thats a need.
Could you let us know about your use-case? We usually recommend putting critical things in the same file, since we don't do any parallelise there (except fullyParallel is true).
Max Schmitt (@mxschmitt) sure, here are our current and future use-cases as far i can tell for now.
We need to increment numbers, earch number can only be used once.
a) read the latest number
b) fill the UI with the latest number + 1 and other infos, this takes about 40s
c) submit the form -> only one test will pass
We need to do UI operations calling external interfaces to other applications.
If this interface is called concurrently it is locked, it is not desinged for concurrent uses.
(future) Integrate hardware into the process and trigger actions on it. We can only trigger one by one to not disturb each others (e.g. due the reset of the hardware before starting the actual test), be able to assign the logs / generate data to a test run.
We might workaround for 1. and 2. by using different users for earch worker (based on the worker index?), but they will use the same data. So we probably must use different data for each worker, but then we need to get the base data maintained in the external applications too. This approach won't scale if we need more workers in the future.
We might workaround for 1. and 2. by using different users for earch worker (based on the worker index?), but they will use the same data.
Can you elaborate on what is wrong with using the same data for each of the test users running in parallel?
If this interface is called concurrently it is locked, it is not desinged for concurrent uses.
If the interface is not designed for concurrent use you'd better run your tests in serial mode (or have a unique user per parallel worker). Why is it not an option for you? As far as I understand, you want to serialize calls to the service rather than entire tests and this would be outside of playwright scope.
I think i need to explain where the concurrency is comming from, this is done to reduce the testing time with different browsers. fullyParallel is false, workers is 3 and projects is 3 (one project for each browser).
Each worker will process the tests serial, but the different browsers will all start at the same test, following the same order of tests. So we need a locking between the workers (in this case browsers) and not inside one worker.
Can you elaborate on what is wrong with using the same data for each of the test users running in parallel?
We cannot check the processing is correct for each test run, if the test runs will concurrently overwrite the results.
If this interface is called concurrently it is locked, it is not desinged for concurrent uses.
this is what is currently happening on the time line, the tests before the critical area are taking different amount of time, so we will not hit the test at the same time, but still while another browser is running:
00:08:02 Chrome - will upload data
00:09:10 Firefox- will upload data
00:08:03 Chrome - data is processing
00:09:13 Firefox - upload failed / due to Chrome data is processing
00:11:00 Chrome - data is processed
00:11:01 Chrome - check the data
Serializing the single calls to the service will not ensure the "check the data" step will pass, a different browser might have overwritten the data in the mean time, so we would need to lock until the complete test is done.
Reacted by apis3445, Kaoru Shirai, Przemyslaw Malolepszy, David Alejandro and Fred
I'm testing a Call Center webRTC application, in which some actions needs to be evaluated before / during / after a call is placed. Of course users can't be active on 2 calls at the same (caller and callee and supervisor).
Creating 1 set of users per test isn't viable either ( would be 3 users per test X number of context [local, ci, regression, healthcheck, smoketests] X environments [local, dev, staging, nightly, live] X each browsers we need to support [chrome, ff, webkit]
Most tests that do not involve placing calls could be fully parallel and it wouldn't be an issue, however, anything that has to place a call cannot be executed in that fashion.
As mentioned above, using dependencies wouldn't really help as a single failure would prevent the subsequent project to run.
Reacted by kendoxsta, Camo30, mcengel and Tobias43
I am currently testing a document management system that is structured into multiple modules. We designed our test structure to mirror the organization of the modules in our project, ensuring that each functionality has its own dedicated test file. However, we are facing a challenge: our modules sometimes modify or utilize the global settings of the system, leading to interference between tests.
Our current solution is to consolidate all these tests into a single test file. This approach has several drawbacks, including the need to increase our global timeout due to the sheer number of tests, even when using test.slow().
Another example involves our Statistics Module. In our system, users can track statistics such as the number of logins or document uploads over a specific time period. The page for activating tracking and the page for viewing the tracked data are two distinct modules, yet they must reside in the same test file.
While it is possible to refactor our teststructure so that all interfering tests are grouped together, this would not only be confusing and unintuitive but also inefficient in many cases. For instance, consider three tests: A, B, and C. Tests A and B interfere with each other, as do tests B and C. Without a locking mechanism, I would be forced to place all three tests in one test file, even though tests A and C could run in parallel without any issues.
I have a single test that uses some canned data, modifies that data, and then resets the data. I want this test to run in multiple browsers, and have most of the tests in the suite run in parallel. But if a firefox worker and a chrome worker both run this test at the same time, the state can get mangled.
Options to solve this:
Create one dataset for each project: more data to track
Separate the test runners to run this test in each project sequentially, and other runs in parallel: more complicated configuration to maintain
Run all tests sequentially: slow
Put each browser case for this test in a single file so that file is run sequentially: odd special case, and some code reuse. (Probably how I'm going to handle it without this locking mechanism)
A simpler method would be if a test case could be given a lock, and the playwright test worker would skip any tests that are currently locked.
In the rare case I have tests I only want to run in a specific browser I've already set up a mechanism for it so that's a plus. I'm not sure if this helps with other use cases for a lock.
On my end I gave up waiting, ended up creating a resource lock service, tests requests a lockable resource, service either accept of denies the lock according to availability.
Computing the resource to request is the test's responsibility, service is as "dumb" as it can be.
Activity
cpolera commentedon Mar 8, 2023
You could probably use the new
TestProject.dependenciesto have a project that runs the sequential tests before running the rest of the tests.see: https://github.com/microsoft/playwright/releases/tag/v1.31.0
edit: actually they probably wont work since a single failure in the dependency will prevent running the second project.
At that point I'd say its probably best to just run two separate projects and have them write to the same directory for the HTML report if thats a need.
mxschmitt commentedon Mar 8, 2023
Looks like a duplicate of #14084 to me.
joerg1985 commentedon Mar 8, 2023
The other one is per test, this one is about more dynamic locks.
mxschmitt commentedon Mar 9, 2023
Could you let us know about your use-case? We usually recommend putting critical things in the same file, since we don't do any parallelise there (except fullyParallel is true).
joerg1985 commentedon Mar 15, 2023
Max Schmitt (@mxschmitt) sure, here are our current and future use-cases as far i can tell for now.
We need to increment numbers, earch number can only be used once.
a) read the latest number
b) fill the UI with the latest number + 1 and other infos, this takes about 40s
c) submit the form -> only one test will pass
We need to do UI operations calling external interfaces to other applications.
If this interface is called concurrently it is locked, it is not desinged for concurrent uses.
(future) Integrate hardware into the process and trigger actions on it. We can only trigger one by one to not disturb each others (e.g. due the reset of the hardware before starting the actual test), be able to assign the logs / generate data to a test run.
We might workaround for 1. and 2. by using different users for earch worker (based on the worker index?), but they will use the same data. So we probably must use different data for each worker, but then we need to get the base data maintained in the external applications too. This approach won't scale if we need more workers in the future.
yury-s commentedon Mar 15, 2023
Can you elaborate on what is wrong with using the same data for each of the test users running in parallel?
If the interface is not designed for concurrent use you'd better run your tests in serial mode (or have a unique user per parallel worker). Why is it not an option for you? As far as I understand, you want to serialize calls to the service rather than entire tests and this would be outside of playwright scope.
joerg1985 commentedon Mar 16, 2023
I think i need to explain where the concurrency is comming from, this is done to reduce the testing time with different browsers. fullyParallel is false, workers is 3 and projects is 3 (one project for each browser).
Each worker will process the tests serial, but the different browsers will all start at the same test, following the same order of tests. So we need a locking between the workers (in this case browsers) and not inside one worker.
We cannot check the processing is correct for each test run, if the test runs will concurrently overwrite the results.
this is what is currently happening on the time line, the tests before the critical area are taking different amount of time, so we will not hit the test at the same time, but still while another browser is running:
00:08:02 Chrome - will upload data
00:09:10 Firefox- will upload data
00:08:03 Chrome - data is processing
00:09:13 Firefox - upload failed / due to Chrome data is processing
00:11:00 Chrome - data is processed
00:11:01 Chrome - check the data
Serializing the single calls to the service will not ensure the "check the data" step will pass, a different browser might have overwritten the data in the mean time, so we would need to lock until the complete test is done.
1 remaining item
dacloutier-logmein commentedon Apr 23, 2024
Adding another use case here.
I'm testing a Call Center webRTC application, in which some actions needs to be evaluated before / during / after a call is placed. Of course users can't be active on 2 calls at the same (caller and callee and supervisor).
Creating 1 set of users per test isn't viable either ( would be 3 users per test X number of context [local, ci, regression, healthcheck, smoketests] X environments [local, dev, staging, nightly, live] X each browsers we need to support [chrome, ff, webkit]
Most tests that do not involve placing calls could be fully parallel and it wouldn't be an issue, however, anything that has to place a call cannot be executed in that fashion.
As mentioned above, using dependencies wouldn't really help as a single failure would prevent the subsequent project to run.
mcengel commentedon Dec 3, 2024
Adding Yet Another Use Case
I am currently testing a document management system that is structured into multiple modules. We designed our test structure to mirror the organization of the modules in our project, ensuring that each functionality has its own dedicated test file. However, we are facing a challenge: our modules sometimes modify or utilize the global settings of the system, leading to interference between tests.
Our current solution is to consolidate all these tests into a single test file. This approach has several drawbacks, including the need to increase our global timeout due to the sheer number of tests, even when using test.slow().
Another example involves our Statistics Module. In our system, users can track statistics such as the number of logins or document uploads over a specific time period. The page for activating tracking and the page for viewing the tracked data are two distinct modules, yet they must reside in the same test file.
While it is possible to refactor our teststructure so that all interfering tests are grouped together, this would not only be confusing and unintuitive but also inefficient in many cases. For instance, consider three tests: A, B, and C. Tests A and B interfere with each other, as do tests B and C. Without a locking mechanism, I would be forced to place all three tests in one test file, even though tests A and C could run in parallel without any issues.
patrickmullen-b2d commentedon Aug 20, 2025
I have a single test that uses some canned data, modifies that data, and then resets the data. I want this test to run in multiple browsers, and have most of the tests in the suite run in parallel. But if a firefox worker and a chrome worker both run this test at the same time, the state can get mangled.
Options to solve this:
A simpler method would be if a test case could be given a lock, and the playwright test worker would skip any tests that are currently locked.
patrickmullen-b2d commentedon Aug 20, 2025
It's not that bad. Here's my tsconfig:
Then in my test file:
In the rare case I have tests I only want to run in a specific browser I've already set up a mechanism for it so that's a plus. I'm not sure if this helps with other use cases for a lock.
alexchexes commentedon Feb 20, 2026
Any chance this will be considered to be implemented?
dacloutier-logmein commentedon Feb 23, 2026
On my end I gave up waiting, ended up creating a resource lock service, tests requests a lockable resource, service either accept of denies the lock according to availability.
Computing the resource to request is the test's responsibility, service is as "dumb" as it can be.
feat(test-runner): support named test locks