kanak
kanak

Reputation: 593

Parallely running parameterized tests in pytest

I wanted to run parameterized test functions in parallel. This is for a concurrency testing scenario. Same testcase runs in parallel with different parameters in a device. After completing all the parameterized variant of one test function, I want to proceed with the next one.

If we take this simple example, I want to run all 4 instances of test_even parallely and then move to test_odd.

@pytest.mark.parametrize("x", range(4))
def test_even(x):
    assert x % 2 == 0        
@pytest.mark.parametrize("x", range(4))
def test_odd(x):
    assert x % 2 != 0

Is it possible to do in pytest? I checked xdist, but could not find this type of support. Could anybody please give some pointers on how to implement this in pytest?

Upvotes: 33

Views: 10441

Answers (1)

Bastian Venthur
Bastian Venthur

Reputation: 16710

I'd recommend using xdist, from their website it does:

The pytest-xdist plugin extends pytest with new test execution modes, the most used being distributing tests across multiple CPUs to speed up test execution...

It does also parallelize your parametrized tests by default.

Here's an example:

import pytest

@pytest.mark.parametrize("foo", range(10))
def test_bar(foo):
    assert True
pytest -n 2 -v
================================================================================================ test session starts ================================================================================================
platform linux -- Python 3.10.4, pytest-7.1.2, pluggy-1.0.0 -- /tmp/test/venv/bin/python3
cachedir: .pytest_cache
rootdir: /tmp/test
plugins: xdist-2.5.0, forked-1.4.0
[gw0] linux Python 3.10.4 cwd: /tmp/test
[gw1] linux Python 3.10.4 cwd: /tmp/test
[gw0] Python 3.10.4 (main, Apr  2 2022, 09:04:19) [GCC 11.2.0]
[gw1] Python 3.10.4 (main, Apr  2 2022, 09:04:19) [GCC 11.2.0]
gw0 [10] / gw1 [10]
scheduling tests via LoadScheduling

test/test_foo.py::test_bar[1] 
test/test_foo.py::test_bar[0] 
[gw1] [ 10%] PASSED test/test_foo.py::test_bar[1] 
[gw0] [ 20%] PASSED test/test_foo.py::test_bar[0] 
test/test_foo.py::test_bar[3] 
[gw1] [ 30%] PASSED test/test_foo.py::test_bar[3] 
test/test_foo.py::test_bar[2] 
test/test_foo.py::test_bar[4] 
[gw0] [ 40%] PASSED test/test_foo.py::test_bar[2] 
[gw1] [ 50%] PASSED test/test_foo.py::test_bar[4] 
test/test_foo.py::test_bar[6] 
test/test_foo.py::test_bar[5] 
[gw1] [ 60%] PASSED test/test_foo.py::test_bar[6] 
[gw0] [ 70%] PASSED test/test_foo.py::test_bar[5] 
test/test_foo.py::test_bar[8] 
test/test_foo.py::test_bar[7] 
[gw1] [ 80%] PASSED test/test_foo.py::test_bar[8] 
test/test_foo.py::test_bar[9] 
[gw0] [ 90%] PASSED test/test_foo.py::test_bar[7] 
[gw1] [100%] PASSED test/test_foo.py::test_bar[9] 

================================================================================================ 10 passed in 0.28s =================================================================================================

Upvotes: 9

Related Questions