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.1

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.1
File Size Uploaded
pytest_resources-0.2.1.tar.gz 28.3 kB Details

Built distribution (wheel)

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

Total release size: 46.7 kB

Release files / pytest_resources-0.2.1.tar.gz

Download URL pytest_resources-0.2.1.tar.gz
Size 28.3 kB
Tags Source
SHA-256 checksum
How to use checksums
b34618dba9dc60abb89193f7e0351cebcfd715cc9e8d00fedb14cf908ac03bd6
BLAKE2b-256 checksum
How to use checksums
a6c6c25469a93271a893bdf156aa72777b98414674048100c962dbf0d0dfbcf3
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.1-py3-none-any.whl

Download URL pytest_resources-0.2.1-py3-none-any.whl
Size 18.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
6278989c44bfc266943554110a4f804e5e2b01213dc45ab546a3b22da7b2e5c4
BLAKE2b-256 checksum
How to use checksums
98c85403fcd0a21ff7740d143199ad2cd23a5ce5327d6e1c54702d53ef534228
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

This release

0.2.1 This release

2 release files

0.2.0

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