Skip to main content
Pre-release

This release is a pre-release and may not be stable for production use.

voci

PyPI CI Coverage Python 3.13 | 3.14 MIT License uv Ruff Pyrefly

A concurrent test runner for async Python. voci runs your whole suite in one process on one event loop, with every test as a concurrent asyncio task. For a suite that spends its time waiting — on a database, on an ASGI app, on a network stub — that turns wall-clock time from the sum of your tests into roughly the slowest one, with a single connection pool and a single set of imports behind it.

Tests declare what they need as parameter defaults, the way FastAPI routes do. There is no conftest.py and no name-based lookup: a fixture is a function you import, so "go to definition" works, renames are safe, and a typo is an ImportError at collection rather than a mystery at run time. When a fixture is a side effect no test needs the value of, a module — or a package, for everything under it — declares it once: voci.use(reset_cache), the way a FastAPI router declares dependencies for every route on it. Assertions keep the introspection you already know — voci vendors pytest's assertion rewriter, so assert a == b still prints a real diff.

# tests/fixtures.py
from typing import Annotated

import voci
from voci import Depends


@voci.fixture(scope="session")
async def engine() -> AsyncIterator[AsyncEngine]:
    engine = create_async_engine("sqlite+aiosqlite:///./test.db")
    yield engine
    await engine.dispose()


@voci.fixture()
async def session(engine: Annotated[AsyncEngine, Depends(engine)]) -> AsyncIterator[AsyncSession]:
    """A transaction per test, always rolled back — so tests share one engine safely."""
    async with engine.connect() as conn:
        transaction = await conn.begin()
        yield AsyncSession(bind=conn)
        await transaction.rollback()


# tests/test_users.py
from typing import Annotated

from voci import Depends

from tests.fixtures import session


async def test_create_user(db: Annotated[AsyncSession, Depends(session)]) -> None:
    db.add(User(email="alice@example.com"))
    await db.flush()

    assert await db.scalar(select(func.count()).select_from(User)) == 1
$ voci
PASS  tests/test_users.py                        10 tests  Σ 3.84s
PASS  tests/test_orders.py                       12 tests  Σ 7.29s

22 tests · 22 passed · 1.14s wall (9.8x concurrency)

The last line is the one to watch: the multiplier shows what running concurrently bought you over the sum of every test's own duration (each file's Σ, above).

Install

You only need Python 3.13+ - voci has no dependencies.

uv add voci --dev          # or: pip install voci

Configure

Everything is optional. voci reads [tool.voci] from the nearest pyproject.toml:

[tool.voci]
testpaths = ["tests"]
concurrency = 16                   # tests in flight at once
timeout = 60                       # per-test budget, in seconds
env = { ENVIRONMENT = "test" }

CLI flags win over config, which wins over the defaults:

voci                              # run everything
voci tests/test_users.py          # run one file
voci tests/test_users.py::test_create[admin]   # run one test, or one of its cases
voci -k "users and not slow"      # select by substring of the test id
voci -m "smoke"                   # select by @voci.tag
voci --serial                     # exactly serial — the first debugging step
voci -x                           # stop at the first failure, cancelling what is in flight
voci --durations 10               # the slowest tests, to tune --concurrency by
voci --loop-watchdog 10           # how long the loop may block before voci names the call
voci --collect-only               # print the ids that would run, and stop
voci -s                           # live, id-prefixed output instead of captured

Where to go next

  • examples/ — three worked suites: a FastAPI + async SQLAlchemy CRUD API, a pure-async library, and shared resources under concurrency. Each is runnable.
  • ROADMAP.md — what isn't built yet, and what's next.
  • plans/rationale.md — why voci is shaped the way it is. Read this before changing anything central to it.

Status

Pre-release, ahead of v0.1. The core is real and exercised by voci's own suite and the three examples: discovery, dependency injection with four scopes and inverted teardown, concurrent execution with per-test timeouts, capture, assertion introspection, selection, and the reporter. Fair scheduling around shared resources, the migration tool, and machine-readable reports are still ahead — see ROADMAP.md. The public API is not frozen yet.

Trade-offs

voci is not pytest and does not aim to be compatible with it. There is no plugin ecosystem and no hook system — dependency injection is the extension point. Adopting it means rewriting your fixture wiring, and it requires Python 3.13+. Linux and macOS are supported; Windows is best-effort.

unittest.mock keeps working, at a price: mock.patch writes to a module or class, which every concurrently running test would see, so voci runs a patch-decorated test alone and reports what that cost. A patch opened inside a test body fails that test unless it is marked @voci.solo. examples/02-async-library walks the alternatives.

Metadata

Release files for voci 0.1.0rc4

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for voci 0.1.0rc4
File Size Uploaded Provenance
voci-0.1.0rc4.tar.gz 1.0 MB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for voci 0.1.0rc4
File Interpreter ABI Platform
voci-0.1.0rc4-py3-none-any.whl Python 3 none any Details

Total release size: 1.3 MB

Release files / voci-0.1.0rc4.tar.gz

Download URL voci-0.1.0rc4.tar.gz
Size 1.0 MB
Tags Source
SHA-256 checksum
How to use checksums
e3532b3d47b8d2073ea8f8edcd705f50bc7bb61da8c4490df8344e368b0e4dad
BLAKE2b-256 checksum
How to use checksums
c8e90c76f872a729076536856d0ef0a628f6ad3c9916316003bf731049ae70de
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 10, 2026.

Transparency log

Release files / voci-0.1.0rc4-py3-none-any.whl

Download URL voci-0.1.0rc4-py3-none-any.whl
Size 261.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
b8641cc0628e729389130c08ada19e928530070f09d4024bc6a0498689033d56
BLAKE2b-256 checksum
How to use checksums
f42766ddb777f6642db18954dac128767683f945a6b424426de9cd6343e57228
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 10, 2026.

Transparency log

Security for voci 0.1.0rc4

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for voci-0.1.0rc4.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 10, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page