Skip to main content

pytest-resources

Lazy, typed, attribute-navigable fixtures for test resource files — JSON / JSONC / YAML / TOML / INI decoded through e-serde by default, extensible to any canonical bytes -> object loader, and anything else handed back as raw bytes.

You point it at one or more directories of sample files; it recursively indexes the tree without reading anything, and you reach, filter and randomise parsed values the way they read:

import pytest_resources as pr

def test_profile(resources: pr.Resources):
    user = resources.structured.user          # sample dir -> dict (decoded, cached)
    body = resources.unstructured.intro       # a .md -> str
    blob = resources.binary.logo              # no codec bound -> raw bytes

    jsons = resources.data.select("*.json")   # filter a folder (glob / regex / kind)
    pick = resources.data.choice("*.json")    # random pick, seeded per run

    ada = resources.make(User, name="ada")    # random model instance    [objects]
    squad = resources.batch(User, 8)          # a typed list of them     [objects]
    pdf = resources.file("report.pdf")        # synthetic file, indexed [files]

Install

uv add --group test "pytest-resources[serde]"   # e-serde default codecs
uv add --group test pytest-resources            # stdlib-only (json + tomllib)
uv add --group test "pytest-resources[objects]" # resources.make()/batch(): random model objects
uv add --group test "pytest-resources[files]"   # resources.file(): synthetic files, 25 formats
uv add --group test "pytest-resources[random]"  # both

The resources fixture auto-loads via the pytest11 entry point — no imports in your conftest.py.

What you get

Idea Mechanism
Recursive index, zero read each root is walked once (off the loop); only paths are held
Lazy + cached a file decodes on first access and is memoized for the session
Attr / item / iter views r.a.b, r["a"]["b"], list(r.a) → list of decoded values
Extract from a folder select/first · paths · walk/awalk (sync/async, lazy) · similar (fuzzy) · as_dict, by glob / regex / kind
Randomise the pick r.a.choice(...) (session-seeded) or pass your own rng
Synthesize on the fly make(Model | hint, seed, **pins) / batch(Model | hint, n) for objects, file(kind | name, ...) for real files adopted into the tree — optional [objects] / [files] / [random] extras
Typed by suffix FileType (StrEnum) resolves the extension; the loader table decodes
Open-ended fallback CSV/TSV/PDF/… and any unknown kind stay raw bytes
Many roots, one tree CLI / ini / pytest_resources_roots hook, merged (later wins), auto-created
Pluggable codecs override or add any kind through the pytest_resource_loaders hook
e-serde default, optional native Rust/C config codecs when installed; stdlib otherwise
Friendly misses EntryNotFoundError / KeyError carry a "did you mean" hint

Configuring the roots

By default the plugin indexes <rootdir>/tests/resources (and creates it if missing). Point it at one or several directories:

# pyproject.toml
[tool.pytest.ini_options]
resources_root = ["fixtures", "fixtures/shared"]   # default: <rootdir>/tests/resources

Or per run (--resources-root is repeatable), or additively from your conftest.py:

from pathlib import Path

def pytest_resources_roots(roots):
    roots.append(Path("tests/fixtures/shared"))

CLI wins over ini, which wins over the default. Every resolved root is merged into one navigable tree; on a top-level clash the later root wins.

Custom loaders (the extension seam)

The plugin never assumes e-serde. Bind any parser declaratively in your conftest.py:

from pytest_resources import FileType
import yaml, csv, io

def pytest_resource_loaders(register):
    register({FileType.CSV: lambda b: list(csv.DictReader(io.StringIO(b.decode())))})
    register({FileType.YAML: yaml.safe_load})

register merges into the session's table, so you can override a default kind as easily as add an unknown one. Kinds left unbound hand back raw bytes.

Programmatic use

Outside pytest, build a tree yourself:

from pathlib import Path
import pytest_resources as pr

tree = pr.build_resources(Path("fixtures"))                      # sync, one root
tree = pr.build_resources([Path("a"), Path("b")])               # merged roots, later wins
tree = await pr.abuild_resources(Path("fixtures"))              # off the event loop
table = pr.default_loaders()                                    # best available codecs

Development

make install   # uv sync + git hooks
make check     # ruff + ty + tach + validate + tests
make ci        # everything the pipeline runs (adds coverage gate + docs + zizmor)

License

MIT

Release files for pytest-resources 0.2.0

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

Source distribution (sdist)

Source distribution for pytest-resources 0.2.0
File Size Uploaded
pytest_resources-0.2.0.tar.gz 28.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for pytest-resources 0.2.0
File Interpreter ABI Platform
pytest_resources-0.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 46.4 kB

Release files / pytest_resources-0.2.0.tar.gz

Download URL pytest_resources-0.2.0.tar.gz
Size 28.0 kB
Tags Source
SHA-256 checksum
How to use checksums
191a996353186a3fa38668d0e74a2ad6eff29d4c819a8538e342924767830a7a
BLAKE2b-256 checksum
How to use checksums
ebaf4ba9c1c36e38c161cbfe1c66b0a8351ac2ec8ea5d12190a69ab1b8b4f29c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / pytest_resources-0.2.0-py3-none-any.whl

Download URL pytest_resources-0.2.0-py3-none-any.whl
Size 18.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
dc7c7d62b775342bc5b383a154dd9c2c5e285f4d8b267edc2278df7e68f0c17b
BLAKE2b-256 checksum
How to use checksums
4c5f2948d3862741d3984f8218d3f47b5e37b373c5891df3d2fee706790ab369
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release history Release notifications | RSS feed

0.3.0

2 release files

0.2.3

2 release files

0.2.2

2 release files

0.2.1

2 release files

This release

0.2.0 This release

2 release files

0.1.0

2 release files

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