.. _sec_parallel_item: **parallel** test item ============================================================ This element is of the following form: .. code-block:: yaml :caption: ``parallel`` test item usage example - parallel: name: My parallel block sync: all branches: - name: Branch A steps: - py_func: name: Long operation file: long_op.py func_name: do_work - name: Branch B wait_for: condition: <| "$(ready_flag)" == "True" |> timeout: 30 steps: - let: name: Mark done values: - branch_b_done: true The ``parallel`` element runs several sequences of items concurrently. Each inner sequence is called a *branch* and runs in its own thread. The parent test item waits for branches to finish according to the ``sync`` policy. Attributes -------------------- * ``branches``: required. A list of branches to execute concurrently. Each branch has a ``name`` and a ``steps`` list (same structure as a ``group`` item). It can also declare a ``wait_for`` precondition (see below). * ``sync``: optional, defaults to ``all``. * ``all``: the parallel item completes when *every* branch has finished. The result is ``PASS`` if no branch returned ``FAIL`` (skipped or disabled branches are ignored, like in ``group``); otherwise ``FAIL``. * ``any``: the parallel item completes as soon as the *first* branch finishes. The remaining branches are stopped (their next test items are not executed). The result is ``PASS`` if at least one branch succeeded. * ``no_fail``: optional. When ``true``, a ``FAIL`` result is forced to ``PASS`` for the parallel item itself (same semantics as for any test item). Branches keep their own result. Branch attributes -------------------- Each entry of ``branches`` is a dict with the following attributes: * ``name``: required. The branch name. Used in reports and as a prefix in the live log output (each line printed by the branch is prefixed with the branch name in square brackets, e.g. ``[Branch A]``, so concurrent branches stay readable). * ``steps``: required. The list of test items executed sequentially inside the branch. * ``wait_for``: optional. Forces the branch to wait until a condition is met before running its steps. If the timeout elapses, the branch returns ``FAIL`` (the steps are not run). Sub-attributes: * ``condition``: a testium expression evaluated repeatedly (every 100 ms) until it returns ``True``. * ``timeout``: maximum wait, in seconds. Defaults to 30. Reporting -------------------- Each branch produces its own row in the SQLite report (with type ``Parallel branch``), in addition to the parent ``Parallel`` row. The ``log`` column of each row contains only the output emitted from that branch's thread, so logs are never mixed between concurrent branches. In the live (terminal / GUI) output, lines emitted from a branch are prefixed with the branch name in square brackets (e.g. ``[Branch A]``). The prefix is not stored in the SQLite log column. Notes -------------------- * A ``sleep`` item inside a branch is interruptible: if another ``sync: any`` branch wins the race, slow ``sleep`` items are aborted within ~50 ms. * A ``py_func`` or ``console`` item inside a branch is **not** interruptible: a ``sync: any`` stop will only take effect after the current item returns. The branch will then skip its remaining steps. * When a user disables a branch in the GUI tree, the branch returns ``SKIP`` instantly without affecting the others (it does *not* win a ``sync: any`` race).