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
I think this is related to #18 but didn't want to clutter the comment history if that's not the case.
I am looking for a way to enforce certain tests, usually the tests within a specific class, to be executed in serial due to that they interfere with each other. I could use -n0 but that would be an overreach - it would apply to the entire test run, not just for a specific class for instance. Would it be possible to just have a decorator directive on the class to 1. instruct xdist to schedule the tests in the class to the same slave as well as 2. instruct them to be run in serial?
If there are other ways of achieving this, I would be interested in that too.
Execute your parallel tests, excluding those with the serial mark:
$ py.test -n auto -m "not serial"
Next, execute your serial tests in a separate session:
$ py.test -n0 -m "serial"
This works perfectly fine in C.I. servers, since it is usually trivial to add an additional command-line to the job.
I will close this now since it is a duplicate of #18, but let me know if you have any other questions.
Reacted by Clinton Blackburn, Dan Girellini, Gabriel Le Breton, H4dr1en, Jason Doherty (Solomo), Shay Ben-Sasson, Yuri Bondarenko, Muhammet Safa GÜNER, Jeffrey Wigger, Avinash Raj and 3 more
You can use --dist=loadscope to group all the tests in the same test class. Here is the doc from pytest-xdist on pypi
By default, the -n option will send pending tests to any worker that is available, without any guaranteed order, but you can control this with these options:
--dist=loadscope: tests will be grouped by module for test functions and by class for test methods, then each group will be sent to an available worker, guaranteeing that all tests in a group run in the same process. This can be useful if you have expensive module-level or class-level fixtures. Currently the groupings can’t be customized, with grouping by class takes priority over grouping by module. This feature was added in version 1.19.
--dist=loadfile: tests will be grouped by file name, and then will be sent to an available worker, guaranteeing that all tests in a group run in the same worker. This feature was added in version 1.21.
@ssbarnea I struggled with this as well and couldn't find a solution anywhere. It's surprising that very few people have encountered this. I ended up implementing a serial fixture with a session-scoped file lock fixture using the filelock package, and it seems to work well. You can add this to your conftest.py:
Then inject the serial fixture in any test that requires serial execution. All tests that use the serial fixture are executed serially while any tests that do not use the fixture are executed in parallel.
Reacted by Daniel Oliveira, Pavlo Shved, Anton Iakovlev, Jonah Kagan, Anthony Schmieder, Garrett Reynolds, René Filip, Roy Moore, Martin Liška, Agriya Khetarpal and 2 more
Reacted by Eric Carmichael, Martin Rueckl and Ramin Gharib
@ssbarnea
Then inject the serial fixture in any test that requires serial execution. All tests that use the serial fixture are executed serially while any tests that do not use the fixture are executed in parallel.
Unfortunately that is not correct. The tests with the serial will be serialized in relation to other tests with the same fixture. Tests without any fixture will be executed in parallel, even at the same time that a serialized test is running.
I need to find a way to have a global lock for my serial tests.
@ssbarnea
Then inject the serial fixture in any test that requires serial execution. All tests that use the serial fixture are executed serially while any tests that do not use the fixture are executed in parallel.
Unfortunately that is not correct. The tests with the serial will be serialized in relation to other tests with the same fixture. Tests without any fixture will be executed in parallel, even at the same time that a serialized test is running.
I need to find a way to have a global lock for my serial tests.
@danielfmo You are correct. That is exactly what will happen. This solution solves the original problem where you want to run some tests serially and others in parallel without having to run pytest twice.
The problem that I had was that there were quite a few functional tests in my test suite that had race conditions when being executed in parallel. It didn't matter to me in what order they were executed as long as they weren't executed at the same time. I was fine running the serial tests in parallel with other tests that did not create race conditions.
If your parallel tests cannot run at the same time as the serial tests, then you could have other dependency issues in your suite that my solution certainly would not fix. I'm not quite sure what problem that you are trying to solve?
They happen to be inside their own modules and I am looking for a solution at module level, so I would not have to annotate tons of tests.
If we can find a solution and document it everyone will benefit as it is very common to have a set of tests that cannot run in parallel. How we select them it could be at module level, file level, class level or individual test functions, ideally being able to mention an optional lock name (for those that may have multiple locks).
They happen to be inside their own modules and I am looking for a solution at module level, so I would not have to annotate tons of tests.
If we can find a solution and document it everyone will benefit as it is very common to have a set of tests that cannot run in parallel. How we select them it could be at module level, file level, class level or individual test functions, ideally being able to mention an optional lock name (for those that may have multiple locks).
Did we got solution for this ?
I have same challenge, few tests want to run parallely and few in serial(when no other tests are run parallely) single trigger of pytest.
I think --dist=loadscope and group the tests by class already solves this? There's also --dist=loadfile can be used for whole modules (all tests in a module are sent to the same worker).
@nicoddemus How about making the serial fixture part of xdist and document it, so anyone could easier reuse?
I do think that the need for serial with xdist is far too popular for not providing support for it, without asking people to DIY their own implementation, which would be more likely to break in various cases.
We properly document this limitations: this fixture as proposed ensures the tests using the fixture will not run concurrently in separate workers. It will not force all tests which use the fixture to execute in the same worker (which is a different use case).
While I understand this might not be ideal, we have to face the reality that I don't see this feature being implemented anytime soon, so providing a fixture which works in 90% of the cases out of the box is good for our users.
It may be helpful to refractor execnet to help this use case more
I agree, but I don't see that happening anytime soon. Just commenting on that to make it clear that we should not block the proposal due to this, and it can be made to work with distributed machines later if someone volunteers to refactor execnet.
We properly document this limitations: this fixture as proposed ensures the tests using the fixture will not run concurrently in separate workers. It will not force all tests which use the fixture to execute in the same worker (which is a different use case).
While I understand this might not be ideal, we have to face the reality that I don't see this feature being implemented anytime soon, so providing a fixture which works in 90% of the cases out of the box is good for our users.
There have been a few changes to the filelock api which may require changes to the example that I provided. Also, the example implements a *nix file lock and may not work for tests being executed on Windows. Additional logic would need to be implemented in a fixture to consider the platform on which tests are being executed.
@ssbarnea I struggled with this as well and couldn't find a solution anywhere. It's surprising that very few people have encountered this. I ended up implementing a serial fixture with a session-scoped file lock fixture using the filelock package, and it seems to work well. You can add this to your conftest.py:
Then inject the serial fixture in any test that requires serial execution. All tests that use the serial fixture are executed serially while any tests that do not use the fixture are executed in parallel.
Ouch, Python 3.11:
> warnings.warn(msg, DeprecationWarning, stacklevel=2)E DeprecationWarning: use poll_interval instead of poll_intervall
I think --dist=loadscope and group the tests by class already solves this? There's also --dist=loadfile can be used for whole modules (all tests in a module are sent to the same worker).
Using --dist=loadfile solved my issue as a subset of my tests that require serial running were accordingly collected in files. Thanks!
@ssbarnea I struggled with this as well and couldn't find a solution anywhere. It's surprising that very few people have encountered this. I ended up implementing a serial fixture with a session-scoped file lock fixture using the filelock package, and it seems to work well. You can add this to your conftest.py:
Then inject the serial fixture in any test that requires serial execution. All tests that use the serial fixture are executed serially while any tests that do not use the fixture are executed in parallel.
Ouch, Python 3.11:
> warnings.warn(msg, DeprecationWarning, stacklevel=2)
E DeprecationWarning: use poll_interval instead of poll_intervall
Causes pytest to fail because of warn == error.
This is not a Python 3.11 issue but an update to the filelock API that was introduced in version 3.4.0 that was released on November 16, 2021 (which was after my comment on April 22, 2020). You should be able to just update the poll_intervall keyword argument in the fixture function and the warning should go away.
Does this solution lead to unnecessarily stalling other processes that have to wait for a lock? Example: 4 workers in total and if you're unlucky it happens that all 4 of them will want to execute serial tests now, this means that 3 workers will be starving while only one worker actually works, then 2, then 1, etc. This is contrary to an approach where serial tests could be "smartly" scheduled to be executed in a way that they "intersect" as little as possible, while parallel tests keep on running as much as possible.
Activity
nicoddemus commentedon Aug 18, 2016
Hey @betamos,
This is what #18 is about, unfortunately nobody got the time to work on it yet.
Here's a solution that works at my workplace:
Mark the tests you want to execute serially with a special mark, say
serial:Execute your parallel tests, excluding those with the
serialmark:Next, execute your serial tests in a separate session:
This works perfectly fine in C.I. servers, since it is usually trivial to add an additional command-line to the job.
I will close this now since it is a duplicate of #18, but let me know if you have any other questions.
evbo commentedon Jul 5, 2017
Is there additional setup to use the "n" option, @nicoddemus ?:
nicoddemus commentedon Jul 5, 2017
It seems you need to install
pytest-xdistssbarnea commentedon Oct 4, 2019
@nicoddemus Any idea if there is a better way to make some tests serial without having to run pytest twice?
larsblumberg commentedon Nov 29, 2019
There's this post on Stackoverflow which might help:
christopheraranda commentedon Apr 22, 2020
@ssbarnea I struggled with this as well and couldn't find a solution anywhere. It's surprising that very few people have encountered this. I ended up implementing a
serialfixture with a session-scoped file lock fixture using thefilelockpackage, and it seems to work well. You can add this to yourconftest.py:Then inject the
serialfixture in any test that requires serial execution. All tests that use theserialfixture are executed serially while any tests that do not use the fixture are executed in parallel.danielfmo commentedon Jul 31, 2020
Unfortunately that is not correct. The tests with the
serialwill be serialized in relation to other tests with the same fixture. Tests without any fixture will be executed in parallel, even at the same time that a serialized test is running.I need to find a way to have a global lock for my serial tests.
christopheraranda commentedon Jul 31, 2020
@danielfmo You are correct. That is exactly what will happen. This solution solves the original problem where you want to run some tests serially and others in parallel without having to run pytest twice.
The problem that I had was that there were quite a few functional tests in my test suite that had race conditions when being executed in parallel. It didn't matter to me in what order they were executed as long as they weren't executed at the same time. I was fine running the serial tests in parallel with other tests that did not create race conditions.
If your parallel tests cannot run at the same time as the serial tests, then you could have other dependency issues in your suite that my solution certainly would not fix. I'm not quite sure what problem that you are trying to solve?
ssbarnea commentedon Jul 31, 2020
What @christopheraranda describes is almost identical with my use case at https://github.com/ansible-community/molecule/tree/master/molecule/test -- where I want to run all unit tests in parallel and all functional tests in serials.
They happen to be inside their own modules and I am looking for a solution at module level, so I would not have to annotate tons of tests.
If we can find a solution and document it everyone will benefit as it is very common to have a set of tests that cannot run in parallel. How we select them it could be at module level, file level, class level or individual test functions, ideally being able to mention an optional lock name (for those that may have multiple locks).
bkashigar commentedon Nov 26, 2021
Did we got solution for this ?
I have same challenge, few tests want to run parallely and few in serial(when no other tests are run parallely) single trigger of pytest.
nicoddemus commentedon Nov 26, 2021
Hi,
I think
--dist=loadscopeand group the tests by class already solves this? There's also--dist=loadfilecan be used for whole modules (all tests in a module are sent to the same worker).ssbarnea commentedon Aug 8, 2022
@nicoddemus How about making the serial fixture part of xdist and document it, so anyone could easier reuse?
I do think that the need for serial with xdist is far too popular for not providing support for it, without asking people to DIY their own implementation, which would be more likely to break in various cases.
Add serial marker for tests
nicoddemus commentedon Aug 10, 2022
Hi @ssbarnea,
Unless @RonnyPfannschmidt opposes, I'm OK to add that fixture if:
filelockdependencyWhile I understand this might not be ideal, we have to face the reality that I don't see this feature being implemented anytime soon, so providing a fixture which works in 90% of the cases out of the box is good for our users.
RonnyPfannschmidt commentedon Aug 10, 2022
It's important to note that the file lock solution is limited to single machines
It may be helpful to refractor execnet to help this use case more
nicoddemus commentedon Aug 10, 2022
I agree, but I don't see that happening anytime soon. Just commenting on that to make it clear that we should not block the proposal due to this, and it can be made to work with distributed machines later if someone volunteers to refactor execnet.
RonnyPfannschmidt commentedon Aug 10, 2022
Let's first and foremost agree that adding the partial solution is acceptable and should be done sooner rather than later
nicoddemus commentedon Aug 10, 2022
Yeah I agree that we need to agree on that hehehe. I agree 👍
nicoddemus commentedon Aug 10, 2022
We also have a solution for the other use case I mentioned:
#385 (comment)
christopheraranda commentedon Aug 10, 2022
There have been a few changes to the
filelockapi which may require changes to the example that I provided. Also, the example implements a *nix file lock and may not work for tests being executed on Windows. Additional logic would need to be implemented in a fixture to consider the platform on which tests are being executed.egberts commentedon Jul 14, 2024
Ouch, Python 3.11:
Causes pytest to fail because of warn == error.
Zyantist commentedon Oct 9, 2024
Using
--dist=loadfilesolved my issue as a subset of my tests that require serial running were accordingly collected in files. Thanks!christopheraranda commentedon Oct 15, 2024
This is not a Python 3.11 issue but an update to the filelock API that was introduced in version 3.4.0 that was released on November 16, 2021 (which was after my comment on April 22, 2020). You should be able to just update the
poll_intervallkeyword argument in the fixture function and the warning should go away.Alexander-Shukaev commentedon Apr 29, 2025
Does this solution lead to unnecessarily stalling other processes that have to wait for a lock? Example: 4 workers in total and if you're unlucky it happens that all 4 of them will want to execute serial tests now, this means that 3 workers will be starving while only one worker actually works, then 2, then 1, etc. This is contrary to an approach where serial tests could be "smartly" scheduled to be executed in a way that they "intersect" as little as possible, while parallel tests keep on running as much as possible.
nicoddemus commentedon May 6, 2025
Indeed it does.