punit.parallelism#
Parallelism for pUnit.
pUnit provides three mechanisms for controlling test execution parallelism: the ``–parallelism [THREADS]`` CLI flag, the ``@parallel`` decorator, and the ``@sequential`` decorator.
CLI flag#
The --parallelism [THREADS] option enables multi-threaded parallel execution.
Each worker thread runs its own asyncio event loop for isolation.
--parallelism(bare flag, no number) runs tests usingcpu_count // 2workers.--parallelism Nruns tests using N workers.No flag means tests run sequentially, one after another.
When parallel mode is active the runner processes each test file in four batches: parallel facts, parallel theories, sequential facts, then sequential theories.
@parallel decorator#
Marking a fact or theory with @parallel triggers auto-enable mode.
When pUnit scans the test package and finds at least one @parallel
decorated test (and no --parallelism flag was given on the CLI):
Parallel execution is enabled automatically with
cpu_count // 2workers.Only
@parallel-marked tests run in the concurrent batch.All other tests are treated as sequential (as if they carried
@sequential).
Applying @parallel to a class marks every method of that class.
@parallel is a no-op when --parallelism is specified on the CLI; the
CLI flag takes full priority.
@sequential decorator#
Marking a fact or theory with @sequential forces it to run as a
sequential test after all parralel tests for that file have
completed. This lets you co-run certain tests one-at-a-time inside
an otherwise parallel test suite (for example, tests that share mutable
state).
When no @parallel decorator is present and --parallelism is not used
on the CLI, all tests run sequentially (the default).
Examples#
Enable parallel mode for the entire test package via CLI:
punit tests/ --parallelism 4
Run only selected tests in parallel – no CLI flag needed:
from punit import fact, parallel
@fact
@parallel
def test_network_io():
...
@fact
def test_database_setup():
# Runs sequentially alongside the parallel tests
...
Mix parallel and sequential tests inside a parallel suite:
from punit import fact, parallel, sequential
@parallel
class SlowTests:
@fact
def test_heavy_computation(self):
...
@fact
@sequential
def test_shared_file_handle(self):
# Runs one-at-a-time after all other SlowTests finish
...
- class ThreadPool(parallelism)#
Bases:
objectManages a pool of worker threads, each with its own asyncio event loop.
The pool follows the context-manager protocol:
__enter__starts the pool,__exit__waits for all in-flight work to finish and shuts down the workers.Parameters#
- parallelismint
Maximum number of tasks to run in parallel. This also equals the number of worker threads. Must be at least 1.
- dispatch(coro)#
Dispatch coro to be executed on a worker thread.
Returns a
_TaskInfothat can be checked withwait().- Return type:
_TaskInfo
- wait(task, timeout=None)#
Block until task’s coroutine has completed.
- Return type:
None
- parallel(target)#
Mark a test function, method, or class for parallel execution.
When pUnit detects any
@parallel-decorated tests in a test package at runtime, it automatically triggers (multi-threaded) parallel execution for the entire test run – no--parallelismCLI flag is required.When
@paralleltriggers auto-enable:Only tests marked with
@parallelrun in the parallel batchTests not marked with
@parallelare treated as sequential (as if decorated with@sequential)The thread pool is initialized with
cpu_count // 2workersThis auto-enable is superseded by
--parallelismon the CLI
When
--parallelismis specified on the CLI, this decorator has no effect; the existing--parallelismbehavior takes priority and all non-@sequentialtests run in parallel as before.When applied to a class, all methods of the class are automatically marked as parallel.
The decorator returns the original
targetunchanged; it installs the__punit_parallelmarker attribute on the unwrapped function (or the class object itself for class targets).Parameters#
- targetCallable | type
The test function, method, or class to mark.
Returns#
- Callable
The original, undecorated target.
Example#
from punit import fact, parallel @fact @parallel def my_parallel_test(): assert True class ParallelTestCase: @fact @parallel def test_one(self): assert True @fact def test_sequential(self): # Runs sequentially (not in parallel batch) assert True
- rtype:
Callable[...,Any]
- sequential(target)#
Mark a test function, method, or class for sequential execution.
When pUnit is started with
--parallelism THREADS(where THREADS > 1), tests decorated without@sequentialrun in parallel up to N at any given point.@sequentialtests are not added to the concurrent dispatch queue – after all peers at the same scope finish concurrently, the sequential tests run one after another in their definition order.When applied to a class, all methods of the class are automatically marked as sequential.
The decorator returns the original
targetunchanged; it installs the__punit_sequentialmarker attribute on the unwrapped function (or the class object itself for class targets).- Return type:
Callable[...,Any]
Parameters#
- targetCallable | type
The test function, method, or class to mark.
Returns#
- Callable
The original, undecorated target.
Example#
from punit import fact, sequential @fact @sequential def my_test(): assert True class MyTestCase: @fact @sequential def test_one(self): assert True # Apply @sequential to an entire class -- all methods run sequentially @sequential class SequentialTestCase: @fact def test_one(self): assert True @fact def test_two(self): assert True