Marks¶
A mark is a decorator attaching a fixed value to the underlying function: fixture or test.
For clarity, skip, xfail or timeout applied twice will raise TypeError. Othr marks can be stacked freely.
Skipping and expected failures¶
voci.skipif
¶
Skip when condition holds. Stacks; any one truthy condition skips.
voci.xfail
¶
xfail(
reason: str,
*,
condition: bool | Callable[[], bool] = True,
strict: bool = False,
raises: ExcTypes | None = None,
) -> Callable[[F], F]
Record an expected-failure mark, with reason. A call phase that raises reports
XFAILED instead of FAILED; one that passes reports XPASSED, or fails the test outright
if strict is set. raises, if given, narrows which exception type counts as the expected
failure -- any other exception still reports FAILED. condition expects the failure only
where it holds, read the way skipif's is: a bool, or a zero-argument callable for one
that must not be computed during import.
Selection and execution¶
You can assign string labels to tests, which can then be selected via the CLI.
voci.tag
¶
Attach selection tags to a test, exposed as TestInfo.tags and selectable with -m.
Execution isolation¶
For tests that may not play nicely with concurrency, voci provides isolated execution marks.
voci.timeout
¶
Record a per-test timeout, in seconds, overriding the suite-wide --timeout budget for
this test alone.
voci.solo
¶
Mark this test to run alone, with nothing else scheduled alongside it.
Applied bare, with no parentheses. Such a test is admitted only once nothing else is running, and blocks every other test's admission until it finishes.
voci.isolated
¶
Mark this test to run alone in a subprocess, on its own fresh interpreter and loop.
Applied bare, with no parentheses. Admitted through the same concurrency/exclusive=/solo
gate as every other test -- the subprocess is what's fresh, not the scheduling. A
module-scope fixture this test shares with in-process siblings is set up and torn down
separately inside the subprocess, not shared with them.
Warnings¶
voci.filterwarnings
¶
Filter the warnings this test raises, with action:message:category:module:lineno specs
-- "error", "ignore::DeprecationWarning", "error:.*legacy:UserWarning".
Each spec is layered over the run's own filterwarnings/-W filters, and the last one to
match a warning is the one that decides it: later specs win over earlier ones, and an outer
decorator's win over an inner one's. error raises the warning where it was warned, failing
the phase that raised it. Every spec is parsed here, so a bad one is an error at import.
See Warnings for the filter grammar and how the three tiers of filters are layered.
Parametrization¶
voci.parametrize
¶
parametrize(
argnames: str | Sequence[str],
argvalues: Sequence[object],
*,
ids: Sequence[str]
| Callable[[object], str | None]
| None = None,
) -> Callable[[F], F]
Record a parametrize mark. argnames is "a,b" or ["a", "b"]; with one name, each
entry of argvalues is that value, with several, each entry is a tuple aligned to the
names. Stacked decorators combine in a stable, defined order: outermost varies slowest.
An entry written as case(value, marks=...) carries marks for that one case, folded into
the test's own for the record that case expands into. Expanded into one test per case at
collection.
voci.case
¶
One @parametrize case, carrying marks that reach that case alone.
marks are the very decorators a test carries -- case(2, marks=voci.skip("flaky")),
case(3, marks=[voci.xfail("known"), voci.tag("slow")]) -- and mean for this case what
they would mean written above the def. Every mark but parametrize works this way; the
test's own marks and the case's are folded together, the case's winning where only one of
skip, xfail or timeout can stand.
values are that case's values, one per argname, exactly as they would be written without
the wrapper: case(1, 2) for two argnames, case((1, 2)) for one that takes a tuple.
Stopping a test from within¶
Two exception classes are provided to force a test result from within the body.
voci.Skipped
¶
Bases: BaseException
Raise to skip the running test immediately -- the runtime counterpart of
@voci.skip/@voci.skipif, which decide once at collection instead.
Raised from a fixture or from the test body, it reports the test as skipped with str(self)
as the reason; whatever ran before the raise already ran, and fixtures already acquired are
torn down normally. A BaseException, not an Exception, so a test or fixture body's
except Exception: does not swallow the skip signal.
voci.Failed
¶
Bases: BaseException
Raise to fail the running test immediately, with a message rather than an assertion --
a named spelling of assert False, msg.
A BaseException, not an Exception, for the same reason Skipped is: a broad
except Exception: around a test's own code must not swallow a deliberate failure signal.