Support matrix¶
Every pytest construct a suite can contain, and what migration makes of it. This is the table
behind the codes: a VC214 in an audit summary, a VOCI-TODO[VC214] left in a converted file
and the rewrite rule that put it there all name the same row.
The number blocks the construct by area — VC0xx is fixture wiring, VC1xx marks, VC2xx test
bodies, VC3xx configuration and plugins, VC4xx the things that only change once tests overlap.
Read this to judge what a migration costs before running one. For the same verdict measured
against your own suite rather than in the abstract, run voci-migrate audit.
Converts as it stands¶
Nobody has to read the diff for these. The conversion rewrites them and the audit counts the tests carrying them as clean.
| Code | pytest | voci | Notes |
|---|---|---|---|
| VC001 | @pytest.fixture |
@voci.fixture() |
A fixture becomes a module-level object, and every parameter that requested it by name is annotated Annotated[T, Depends(...)] naming the import. |
| VC002 | @pytest.fixture(params=...) |
@voci.fixture(params=...) |
The fixture keeps its cases, and request.param becomes the factory's own param argument. |
| VC004 | conftest.py fixture | fixtures.py beside the conftest | Every fixture in a conftest.py moves to a fixtures.py beside it, and the tests that used it import it from there. |
| VC005 | a fixture overriding one visible from further out | a specialized fixture chain | The override and every fixture between it and the tests that reach it are generated as a specialized chain named for the directory or class the override rules. |
| VC007 | @pytest.mark.parametrize(..., indirect=True) |
@voci.fixture(params=...) |
The values move onto the fixture as params=: indirect parametrization is a call site choosing a fixture's case, and a voci fixture carries its own cases. |
| VC008 | @pytest.fixture(autouse=True) |
voci.use(...) |
Becomes one voci.use(...) declaration on the module or package the fixture covered, rather than a parameter on each test. |
| VC009 | @pytest.mark.usefixtures on a module or class | voci.use(...) |
Becomes a voci.use(...) declaration covering the same tests. |
| VC011 | request.getfixturevalue("literal") |
a Depends() parameter | A literal name is a static dependency, so it becomes an ordinary Depends() parameter. |
| VC013 | request.addfinalizer(fn) |
yield teardown | An unconditional finalizer becomes the fixture's yield teardown. |
| VC018 | class Test* grouping | class Test* | The class stays as namespacing and each method collects as path.py::TestGroup::test_name. |
| VC026 | a fixture requesting request for its own parametrization | the param argument | request.param in a params= fixture becomes the factory's param argument. |
| VC032 | @pytest.fixture written inside a test class | a module-level fixture named for the class | A voci test class is pure namespacing, with no fixtures of its own, so the factory is lifted to the module level under a name carrying the class's, and the methods that requested it name it there. |
| VC034 | a relative import in a suite module | an absolute import | voci imports test modules under synthetic names, which a leading dot resolves against nothing, so each becomes the absolute import of the same module. |
| VC101 | @pytest.mark.parametrize |
@voci.parametrize |
Becomes @voci.parametrize carrying pytest's own case ids verbatim, so node ids do not move. |
| VC102 | pytest.param(..., marks=...) |
voci.case(..., marks=...) |
Becomes voci.case(*values, marks=...), carrying the same marks translated into their voci spelling, which reach that one case. |
| VC104 | @pytest.mark.skip, @pytest.mark.skipif(bool) |
@voci.skip, @voci.skipif |
Same decorator, same reason. |
| VC105 | @pytest.mark.xfail with a condition | @voci.xfail(condition=...) |
The condition becomes @voci.xfail's own condition=, which decides whether the failure is expected at all. |
| VC107 | xfail_strict |
strict= on each xfail | The ini setting is written into each generated @voci.xfail as strict=. |
| VC108 | @pytest.mark.filterwarnings |
@voci.filterwarnings(...) |
Becomes @voci.filterwarnings(...), which takes the same filter specs and governs the test that carries it alone, whatever else is running. |
| VC109 | a custom mark | @voci.tag(...) |
Becomes @voci.tag(...), selectable with -m, and needs no registration. |
| VC110 | @pytest.mark.asyncio, @pytest.mark.anyio, event_loop fixtures | deleted | voci runs async def tests itself, so the mark and the loop fixtures go away. A backend parametrization the mark carried goes with it, and with it that segment of the test's id. |
| VC111 | @pytest.mark.timeout |
@voci.timeout(...) |
Becomes @voci.timeout(...). |
| VC115 | pytestmark on a module or a class | the same mark on each test | voci reads marks from the test function, and a mark on a class is a collection error, so each mark the assignment applied becomes a decorator on every test it reached. |
| VC201 | capsys |
voci.capture |
Becomes the voci.capture fixture, whose .out and .err read the live buffers. |
| VC204 | caplog.records, caplog.messages |
voci.log_records |
Become the same attributes on voci.log_records. |
| VC206 | caplog.text, caplog.record_tuples, caplog.clear() |
voci.log_records |
Become the same names on voci.log_records, which formats .text from its own records on every read rather than keeping a second stream. |
| VC207 | tmp_path, tmp_path_factory |
tmp_path, tmp_path_factory |
Same names, same pathlib.Path. |
| VC208 | tmpdir, tmpdir_factory |
voci.tmpdir, voci.tmpdir_factory |
Same names, voci.tmpdir/voci.tmpdir_factory's own LegacyPath wrapping .join, .strpath, .write, .mkdir and division the way pytest's own legacy shim does. |
| VC209 | pytest.raises(E, match=...) |
voci.raises |
Becomes voci.raises, matching with re.search as pytest does. |
| VC210 | pytest.raises(E, func, *args) |
voci.raises |
Becomes voci.raises, which has the same callable form: it calls func(*args, **kwargs) under the hood and returns the resulting ExceptionInfo. Left unconverted when match= is among the kwargs, or a **mapping is unpacked into them: pytest forwards match to func there, but voci.raises always intercepts it. |
| VC212 | pytest.approx(scalar) |
voci.approx |
Becomes voci.approx. |
| VC213 | pytest.approx over a list, tuple, or dict | voci.approx |
Becomes voci.approx, which compares a list or tuple elementwise by position and a dict elementwise by key, all under the same tolerances. Left unconverted where a list, tuple, dict, or set is nested one level inside it: voci.approx only walks one level, so there is no position to compare a nested container by. |
| VC214 | pytest.skip(), pytest.fail() as a statement | voci.Skipped, voci.Failed |
voci.skip is a decorator factory, not a runtime call -- calling it in a body builds a decorator and discards it, which would turn a conditional skip into a silent pass, so these become voci.Skipped/voci.Failed, raised directly, instead. |
| VC217 | unittest.mock.patch as a decorator | @mock.patch, scheduled solo | The patch stays as it is and voci schedules the test alone. Injected parameters are emitted after the mock arguments the decorator fills positionally. Tests using it run alone. |
| VC218 | unittest.mock.patch as a context manager | @voci.solo on the test | A patch entered inside a body is invisible until it runs, so the test carries @voci.solo and nothing else runs while it holds. Tests using it run alone. |
| VC301 | testpaths |
testpaths |
Same meaning under [tool.voci]. |
| VC302 | python_files |
test_file_patterns |
Becomes test_file_patterns. |
| VC303 | norecursedirs |
ignore |
Becomes ignore. |
| VC304 | pytest-timeout's timeout setting | timeout |
Becomes the timeout key, which voci applies per test. |
| VC306 | markers, asyncio_mode, and other settings with nothing to configure | dropped | voci tags need no registration and it runs async tests without being told to, so these settings have no counterpart to write. |
| VC307 | filterwarnings |
[tool.voci] filterwarnings | Carried to [tool.voci]'s own filterwarnings, which takes the same filter specs. |
| VC320 | an installed plugin migration deletes | deleted | Its whole job is done by the runner, so the suite loses the dependency. |
| VC321 | an installed plugin with a translation | — | What the suite uses it for has a voci spelling, reached through the rows for the fixtures and marks themselves. |
Converts, with something to check¶
These convert to working code, but something shifted on the way. The rewrite leaves a VOCI-TODO[code] comment in the source at each one.
| Code | pytest | voci | What shifted | What to check |
|---|---|---|---|---|
| VC003 | fixture scope="class" or scope="package" | @voci.fixture(scope=...) |
voci scopes are call, function, module and session. A class-scoped fixture becomes module-scoped and a package-scoped one becomes session-scoped, so each is shared by more tests than it was. | Confirm the fixture tolerates being shared more widely, or split it. |
| VC010 | @pytest.mark.usefixtures on some of a module's tests | voci.use(...) |
voci.use(...) declares a fixture for a whole module, so the fixture reaches the module's other tests too. |
Confirm the other tests in the module tolerate the fixture, or move them out. |
| VC015 | request.node, request.config, request.cls, and every other attribute of request | voci.test_info |
voci.test_info carries the test's id, tags, timeout and worker. Anything else these reach — a node's own marks, ini values, the owning class — has no counterpart. |
Rewrite the use against test_info, or pass what the fixture needs in. |
| VC024 | pytest_generate_tests |
@voci.parametrize with the generated cases | The cases the hook produced are in the dump, ids included, so they convert to an explicit @voci.parametrize — one that lists what this extraction saw and generates nothing new. |
Confirm the frozen case list is what the suite should keep testing. |
| VC025 | pytest_plugins in a conftest | — | Fixtures the named module contributed are translated from the dump like any other, and the declaration itself goes away. | Check the named module for hooks and non-fixture content, which do not travel. |
| VC103 | @pytest.mark.skipif with a string condition | @voci.skipif |
voci takes a bool or a zero-arg callable. A string condition is evaluated by pytest at collection, and a callable is evaluated by voci at run time. | Confirm the condition reads the same at run time as it did at collection. |
| VC106 | @pytest.mark.xfail(run=False) |
@voci.skip |
Nothing in voci marks a test as expected-to-fail without running it, so it becomes a skip and is reported as one. | Confirm a skip is the outcome the suite wants reported. |
| VC114 | a case id composed from more than one axis | @voci.parametrize without ids | pytest builds one id per case out of every axis that varies it — stacked parametrize marks, or a mark over a params= fixture — so no single mark can carry the ids verbatim, and voci composes its own from the values. |
Check any CI configuration, dashboard or --last-failed habit that names these ids, and write an explicit ids= where one matters. |
| VC116 | @pytest.mark.xfail with a string condition | @voci.xfail(condition=...) |
voci takes a bool or a zero-arg callable, so the string becomes a lambda over the same expression, evaluated where the module it reads is already imported. | Confirm the condition reads the same from the converted module as it did in pytest's own namespace. |
| VC202 | capsys.readouterr() more than once in a body | voci.capture |
readouterr() returns a snapshot and clears the buffer; capture.out is cumulative and never cleared, so a second read sees the first read's output too. |
Compare against the text captured so far, or slice off what was already asserted. |
| VC205 | caplog.set_level(...) |
with log_records.set_level(...) | LogRecords.set_level(...) returns a context manager and does nothing until it is entered, so the statement becomes a with block around the rest of the test. Logger levels are process-global. Tests using it run alone. |
Wrap the part of the test that needs the level, and mark the test @voci.solo. |
| VC219 | mocker (pytest-mock) | mock.patch plus @voci.solo | mocker.patch is mock.patch with teardown attached to the fixture, so each call becomes a mock.patch the test enters, and the test runs alone. Tests using it run alone. |
Rewrite each mocker. call as the mock call it wraps. |
| VC305 | addopts |
— | Each flag needs its own answer: some have a voci spelling, some were a plugin's, and unknown [tool.voci] keys are a hard error, so nothing speculative is written. |
Translate the flags you rely on into [tool.voci] or into the CI invocation. |
Needs a decision first¶
voci has somewhere for these to go, but not one the conversion can pick on its own. Each is a blocked test until the suite is changed by hand.
| Code | pytest | Why | What to do |
|---|---|---|---|
| VC006 | conftest override whose chain exceeds the specialization budget | Specializing this override would duplicate more fixtures than the budget allows, which is the point where a generated chain stops being reviewable. | Unwind the override into an explicit seam or a parametrized fixture before converting. |
| VC012 | request.getfixturevalue(computed) |
The name is decided at run time, so nothing static can say which fixture is meant. | Replace the computed lookup with explicit dependencies, or with a factory fixture that takes them. |
| VC014 | request.addfinalizer where no single yield can take its place | A yield fixture hands its value over at one point in the body and tears down after it, so a finalizer registered under a condition, from inside another function, or from somewhere that is not a fixture has nowhere to move to. |
Register the finalizer unconditionally in the fixture's own body, moving any condition inside it. |
| VC017 | request passed to another function or held past setup | The uses cannot be enumerated at the call site, so no per-use translation applies. | Narrow the fixture to the values it actually reads from request. |
| VC019 | setup_method, teardown_method, setup_class, setup_function |
voci builds a fresh instance per test and calls no setup protocol, so these never run. | Move each one's body into a fixture the class declares with voci.use(...). |
| VC027 | conftest override reaching an autouse fixture | A specialized chain gives the subtree its own objects, and a voci.use(...) declares one of them for a directory — so an autouse fixture the override changes would be declared twice over the same tests, once for each definition. |
Request the fixture by name where it is needed, or unwind the override. |
| VC028 | request.getfixturevalue of a name a parameter cannot carry | A parameter names one object for the whole definition, so a name the suite defines in more than one directory, or one asked for where there is no signature to grow, has no parameter to become. | Request the fixture in the signature, or unwind the override that gives the name two meanings. |
| VC029 | indirect parametrization a params= fixture cannot carry | A params= fixture has one case list for every test that reaches it, so a name given different values in different tests, one parametrized alongside a direct axis, one whose fixture already has cases of its own, and one whose values have no literal spelling all have nowhere to go. |
Give the fixture the cases it always has with params=, or take the parametrization off the fixture and pass the value to the test. |
| VC031 | a generated case an explicit parametrize cannot list | A frozen case list is written from the value each case was given, so a value with no literal spelling, and an axis the hook composed with one the test was written with, have nothing this can write. | Write the cases out as a @pytest.mark.parametrize before converting. |
| VC033 | a fixture inside a test class reading its instance | Lifting the factory out of the class takes self away with it, and a self naming anything but an attribute the class body itself binds has no module-level spelling. |
Read the class attribute through the class, or move what the fixture needs off the instance. |
| VC036 | a fixture requested by a positional-only parameter | voci binds every argument by keyword, so a parameter written before the / can never be given the object it names, and moving it out from behind the / would change what the definition can be called with everywhere else. |
Write the parameter after the /, or take the / off the signature. |
| VC113 | two skip, xfail or timeout marks on one test | voci raises when a scalar mark is applied twice, so this is a collection error rather than a last-one-wins. | Keep one, having decided which. |
No voci equivalent¶
voci provides nothing that plays these parts, so a suite that leans on one has to do without it or keep that part under pytest.
| Code | pytest | Why | What to do instead |
|---|---|---|---|
| VC016 | request.config.getoption on a custom pytest_addoption flag | The flag exists because a conftest hook added it to pytest's command line, and voci has no plugin command-line surface for it to be added to. | Read the value from the environment or from configuration instead. |
| VC020 | unittest.TestCase |
voci collects functions and class Test* methods; a TestCase subclass brings its own lifecycle, assertions and skipping. |
Rewrite the class as plain test functions. |
| VC021 | doctests |
voci collects test modules, not docstrings. | Keep running doctests under their own command. |
| VC022 | conftest hook (pytest_configure, pytest_collection_modifyitems, ...) | Hooks are how a pytest plugin reaches into collection and reporting, and voci has no hook protocol. | Decide per hook: fixtures replace setup hooks, and reporting hooks have no counterpart. |
| VC023 | pytest_addoption |
voci's command line is fixed, so a suite cannot add a flag to it. | Read the setting from the environment or from [tool.voci]'s env. |
| VC030 | a fixture an installed plugin provides | The fixture lives in a distribution, not in the suite, so there is no source to move and nothing registers it under voci. | Write the fixture into the suite, or drop the tests that need it. |
| VC112 | a mark an installed plugin acts on | The behaviour was the plugin's, and voci records marks as tags without acting on them. | Replace the mark's effect with a fixture, or drop the tests that need it. |
| VC203 | capfd, capsysbinary, capfdbinary |
voci captures by replacing sys.stdout and sys.stderr, so writes to file descriptor 1 by a subprocess or a C extension are not captured, and there is no binary variant. |
Redirect the subprocess to a file the test reads, or drop the assertion. |
| VC211 | pytest.raises(asyncio.CancelledError) |
Cancellation is how voci enforces timeouts, so voci.raises refuses to swallow it. |
Assert on the cancellation's effect instead of catching it. |
| VC215 | pytest.importorskip("mod") |
There is no imperative skip to reach for at import time. | Guard the import at module level and put @voci.skipif on the tests. |
| VC216 | pytest.warns, recwarn, pytest.deprecated_call |
Recording warnings means installing a process-global filter, which cannot be scoped to one of several tests in flight. | Assert on what the warning accompanies, or catch it inside a @voci.solo test. |
| VC220 | pytestconfig, cache, record_property, pytester and other pytest builtins | These fixtures expose pytest's own configuration, cache and self-test machinery. | Drop the use, or read the value from configuration. |
| VC221 | pytest.approx over a set or a generator expression | Neither has a position to compare by: a set is unordered, and a generator is spent after one read. A numpy array is left unconverted here too, since voci has no numpy dependency to compare it with. | Compare a sorted sequence instead of a set, or a list instead of a generator. |
| VC222 | caplog.handler, caplog.get_records(...) |
voci has no handler object behind voci.log_records, and no per-phase record split for get_records to read. |
Assert on records or messages directly instead of handler; there is no phase-scoped equivalent for get_records. |
| VC223 | pytest.xfail() as a statement | Unlike pytest.skip()/pytest.fail(), this has no runtime target to become: it marks the test as an expected failure and stops it right there, which @voci.xfail(...)'s condition -- decided once at collection, before the test has run at all -- can't reach. |
Lift the condition into @voci.xfail(condition=...), if it's known before the test runs; otherwise let the test fail and mark it @voci.xfail unconditionally. |
| VC308 | log_cli, console_output_style, required_plugins and other reporting settings | These configure pytest's terminal and plugin machinery. | Drop them, or reach for the closest voci flag. |
| VC309 | an ini setting a plugin registered | The setting exists because a plugin asked pytest for it, and unknown [tool.voci] keys are a hard error. |
Drop it with the plugin, or move the value into the environment. |
| VC323 | an installed plugin with no voci path | Nothing in voci provides what it does. | Keep those tests under pytest, or drop the plugin's use. |
| VC324 | a case parametrized onto an event loop other than asyncio | voci runs every async test on asyncio, so the cases a backend fixture produces for another loop have nothing to run on and disappear with it. | Pin the backend fixture to asyncio, and keep the other loop's coverage under pytest. |
Survives conversion, changes under concurrency¶
These translate as written and then mean something different, because voci overlaps the tests that pytest ran one at a time. Most cost the tests carrying them their overlap with the rest of the suite.
| Code | Construct | What changes | What to do |
|---|---|---|---|
| VC322 | an installed plugin that mutates process-global state | It works, and what it changes is visible to every test running at the same time. Tests using it run alone. | Schedule the tests that use it alone, or isolate them. |
| VC401 | monkeypatch |
Every monkeypatch call changes state the whole process shares — an attribute, an environment variable, sys.path, the working directory — which a serial runner made private to the running test. Tests using it run alone. |
Inject the dependency instead, or mark the test @voci.solo; chdir needs @voci.isolated. |
| VC402 | os.environ writes | The environment is process-wide, so a variable one test sets is set for every test in flight. Tests using it run alone. | Set suite-wide values in [tool.voci]'s env, and mark tests that need their own value @voci.solo. |
| VC403 | warnings filter mutation | simplefilter and filterwarnings write a process-global list, and catch_warnings restores it wholesale on exit — including changes another test made meanwhile. Tests using it run alone. |
Mark the test @voci.solo. |
| VC404 | logging level or handler mutation | Logger objects are process-global, so a level a test raises is raised for everything logging at the same time. Tests using it run alone. | Mark the test @voci.solo, or assert on records without changing levels. |
| VC405 | sys.modules surgery or importlib.reload | Replacing or reloading a module rebinds it for every test that has already imported it. Tests using it run alone. | Mark the test @voci.isolated. |
| VC406 | os.chdir |
The working directory belongs to the process, and a relative path elsewhere in the suite resolves against whatever it currently is. Tests using it run alone. | Use absolute paths, or mark the test @voci.isolated. |
| VC407 | locale, decimal context or interpreter limits | These are interpreter-wide settings with no per-task scope. Tests using it run alone. | Mark the test @voci.isolated. |
| VC408 | a globally patched clock (freezegun, time-machine) | Freezing time replaces the clock for the whole process, so every test in flight sees the frozen time. Tests using it run alone. | Inject a clock, or mark the test @voci.solo. |
| VC409 | asyncio.run, get_event_loop, new_event_loop, run_until_complete |
voci runs the test on a loop that is already running, and starting a second loop from inside it fails. | Await the coroutine directly in an async def test. |
| VC410 | a blocking call in an async body | One blocking call in an async def holds the loop, and every other test in flight waits for it. A sync def test is safe: it runs on an executor thread and holds only its own slot. |
Use the async client, or make the test a plain def. |
| VC411 | a module-level or class-level global a test writes | State that outlives a test is shared with every test that reads it, and nothing sequences them any more. | Move the state into a fixture. |
| VC412 | seeded randomness and sequence counters | A seed set in a fixture, or a factory sequence, produced deterministic values because tests drew from it one at a time. | Seed per test, or assert on shape rather than on generated values. |
| VC413 | a fixed external resource | A hardcoded port, path or database worked because one test used it at a time. | Allocate per test, or mark the tests that share it exclusive= on their fixture. |
What no scan can see¶
A dump records what pytest resolved and a parse records what the sources say. Neither reaches these, so the audit names them in its report rather than counting them.
| Code | Construct | Why it is invisible | What to do |
|---|---|---|---|
| VC035 | a suite that reads its own module names | voci imports each test module by path, under a synthetic voci_tests. name that makes two files of the same name in different directories two modules. Anything keyed on __module__ — a class registry, a plugin lookup, a snapshot path — sees that name. |
Key on something the import name does not decide, or move what registers itself out of the test module. |
| VC414 | test-order dependence | A test that passes only because something earlier in the file ran first has nothing in its source saying so. | Run the suite shuffled under pytest before converting. |
| VC415 | fixture teardown timing | pytest tears a module-scoped fixture down when the module's last test finishes; voci tears it down when its last holder releases, with other modules still running. | Check anything that asserts a teardown has happened. |
| VC416 | shared state behind application code | Singleton caches, functools.lru_cache on application functions, ORM identity maps and module-level registries are shared by tests that never mention them. |
Reset them in a fixture, or inject them. |
Installed plugins¶
What migration makes of each plugin it recognizes, by the matrix row that classifies it: VC320 is deleted outright, VC321 translates into something voci already has, VC322 survives but mutates state the whole process shares, and VC323 has no voci path. A plugin absent from this table is reported as unrecognized rather than assumed harmless.
| Plugin | Code | Disposition | Notes |
|---|---|---|---|
pytest-asyncio |
VC320 | mechanical | voci runs async tests itself. |
anyio |
VC320 | mechanical | voci runs async tests itself. |
pytest-trio |
VC323 | unsupported | voci runs tests on asyncio. |
pytest-tornasync |
VC323 | unsupported | voci runs tests on asyncio. |
pytest-xdist |
VC320 | mechanical | voci runs tests concurrently in one process, so there are no workers to distribute across. Its flags live on in CI invocations. |
pytest-randomly |
VC320 | mechanical | Ordering is not voci's to shuffle. A suite that ran green under it is evidence the suite does not depend on order. |
pytest-timeout |
VC320 | mechanical | @voci.timeout(...) and the timeout setting. |
pytest-env |
VC320 | mechanical | [tool.voci]'s env sets the suite's environment. |
pytest-mock |
VC321 | mechanical | mocker becomes mock.patch, and the tests that use it run alone. |
pytest-httpx |
VC321 | mechanical | Transport-level patching, per test, which stays as it is. |
respx |
VC321 | mechanical | Transport-level patching, per test, which stays as it is. |
pytest-recording |
VC321 | mechanical | Transport-level patching, per test, which stays as it is. |
pytest-vcr |
VC321 | mechanical | Transport-level patching, per test, which stays as it is. |
pytest-freezegun |
VC322 | hazard | It patches the process clock for the running test. |
pytest-freezer |
VC322 | hazard | It patches the process clock for the running test. |
pytest-time-machine |
VC322 | hazard | It patches the process clock for the running test. |
factory-boy |
VC322 | hazard | Factory sequences are class-level counters shared by every test drawing from them. |
pytest-django |
VC322 | hazard | Its database fixtures translate through the fixture rows, and its per-test transaction and settings overrides are process-global. |
pytest-flask |
VC322 | hazard | Its app and client fixtures translate through the fixture rows. |
pytest-postgresql |
VC322 | hazard | Its database fixtures translate through the fixture rows; the database itself is a shared resource. |
pytest-cov |
VC323 | unsupported | Coverage of a concurrent single-process run is measured by running coverage around voci, not by a plugin. |
pytest-subtests |
VC323 | unsupported | Nothing in voci reports sub-results. |
pytest-benchmark |
VC323 | unsupported | A timing measurement taken while other tests run means nothing. |
pytest-repeat |
VC323 | unsupported | Nothing in voci repeats a test. |
pytest-rerunfailures |
VC323 | unsupported | Nothing in voci retries a test. |
pytest-flakefinder |
VC323 | unsupported | Nothing in voci repeats a test. |
hypothesis |
VC323 | unsupported | @given rewrites a test's signature, which is where voci reads injected dependencies from. |
pytest-bdd |
VC323 | unsupported | Its step decorators build tests through pytest hooks. |
pytest-splinter |
VC323 | unsupported | Nothing in voci provides browser fixtures. |
pytest's builtin fixtures¶
Every fixture pytest provides without the suite declaring it, and the row that decides what a request for it becomes.
| Fixture | Code | Becomes |
|---|---|---|
request |
VC026 | the param argument |
tmp_path |
VC207 | tmp_path, tmp_path_factory |
tmp_path_factory |
VC207 | tmp_path, tmp_path_factory |
tmpdir |
VC208 | voci.tmpdir, voci.tmpdir_factory |
tmpdir_factory |
VC208 | voci.tmpdir, voci.tmpdir_factory |
capsys |
VC201 | voci.capture |
caplog |
VC204 | voci.log_records |
capfd |
VC203 | — |
capsysbinary |
VC203 | — |
capfdbinary |
VC203 | — |
capteesys |
VC203 | — |
monkeypatch |
VC401 | — |
recwarn |
VC216 | — |
pytestconfig |
VC220 | — |
cache |
VC220 | — |
record_property |
VC220 | — |
record_testsuite_property |
VC220 | — |
record_xml_attribute |
VC220 | — |
pytester |
VC220 | — |
testdir |
VC220 | — |
doctest_namespace |
VC021 | — |