Skip to main content

Pytest plugin that allows you to easily define data-driven fixtures based on external files.

Project description

Fingest — Pytest Data-Driven Fixtures

PyPI version Python versions License: MIT

A pytest plugin that turns JSON, CSV, and XML files into fully-typed, iterable test fixtures — no boilerplate required.

Quick Start

1. Install

pip install fingest

2. Point pytest at your data

# pytest.ini  (or pyproject.toml under [tool.pytest.ini_options])
[pytest]
fingest_fixture_path = tests/data

3. Define fixtures in conftest.py

from fingest import data_fixture, JSONFixture, CSVFixture, XMLFixture

@data_fixture("users.json", description="Test user data")
class user_data(JSONFixture):
    pass

@data_fixture("products.csv", description="Product catalog")
class product_data(CSVFixture):
    pass

@data_fixture("config.xml", description="App configuration")
class config_data(XMLFixture):
    pass

4. Use them in tests

def test_users(user_data):
    assert len(user_data) == 2
    assert "Alice" in [u["name"] for u in user_data]  # iterable!

def test_expensive_products(product_data):
    expensive = product_data.filter_rows(price=lambda p: float(p) > 100)
    assert len(expensive) >= 1

def test_db_host(config_data):
    assert config_data.get_text("database/host") == "localhost"

Fixture Types

BaseFixture

All fixtures inherit from BaseFixture, which gives you:

Feature Example
Length len(fixture)
Truthiness if fixture:
Iteration for item in fixture:
Containment "key" in fixture
Equality fixture_a == fixture_b
Raw data fixture.data

JSONFixture

For dict or list JSON data.

fixture["users"]          # direct indexing
fixture.get("key", None)  # safe access
fixture.keys()            # dict keys
for key in fixture:       # iterate keys (dict) or items (list)
"name" in fixture         # containment check

CSVFixture

For tabular CSV data.

fixture.rows              # all rows as list of dicts
fixture.row_count         # number of rows
fixture.columns           # column names
fixture.get_column("age") # all values from one column
fixture[0]                # first row

# filter with exact values or predicates
fixture.filter_rows(city="NYC")
fixture.filter_rows(price=lambda p: float(p) > 100)

for row in fixture:       # iterate rows
{"name": "Bob"} in fixture  # row membership

XMLFixture

For XML data, powered by lxml.

fixture.root              # root Element
fixture.tag               # root tag name
fixture.find("db/host")   # first matching element
fixture.findall("items/item")  # all matches
fixture.xpath("//feature[@enabled='true']")
fixture.get_text("settings/timeout", default="30")
fixture.to_dict()         # recursive XML → dict conversion

Cloud Storage Adapters

Fingest includes decorators for AWS S3, GCP GCS, and Azure Blob Storage. These are designed for mock-first development: by default, they load data from your local fingest_fixture_path, simulating cloud responses.

1. Define Cloud Fixtures

from fingest import aws_bucket_fixture, gcs_fixture, azure_blob_fixture
from fingest import JSONFixture, CSVFixture, XMLFixture

# AWS S3 (Bucket: "my-bucket", Key: "data/users.json")
@aws_bucket_fixture("my-bucket", "data/users.json", description="S3 users")
class s3_users(JSONFixture): pass

# GCP GCS (Bucket: "my-bucket", Key: "data/products.csv")
@gcs_fixture("my-bucket", "data/products.csv", description="GCS products")
class gcs_products(CSVFixture): pass

# Azure Blob (Container: "my-container", Blob: "data/config.xml")
@azure_blob_fixture("my-container", "data/config.xml", description="Azure config")
class azure_config(XMLFixture): pass

2. Mocking vs. Live Mode

The adapters are in mock mode by default. They will look for files in your local fixture directory (e.g., tests/data/data/users.json).

To enable live mode (hitting the real cloud SDKs), set mock=False. Note that cloud SDKs (boto3, google-cloud-storage, azure-storage-blob) are optional dependencies and must be installed separately.

@aws_bucket_fixture("my-bucket", "data/users.json", mock=False)
class live_s3_data(JSONFixture): pass

Function-Based Fixtures

For custom data transformations or fixtures that depend on other pytest fixtures:

@data_fixture("raw_data.json")
def processed_users(data):
    """data is injected by fingest; remaining params are pytest fixtures."""
    return [{"name": f"{u['first']} {u['last']}"} for u in data["users"]]

@data_fixture("config.json")
def config_with_db(data, database_fixture):
    """Depends on another pytest fixture — works seamlessly."""
    return {"config": data, "db": database_fixture}

Custom Data Loaders

Support any file format by registering a loader:

from fingest import register_loader
import yaml

def yaml_loader(path):
    with open(path) as f:
        return yaml.safe_load(f)

register_loader("yaml", yaml_loader)

Or use a one-off loader for a single fixture:

@data_fixture("data.toml", loader=toml_loader)
class toml_config(BaseFixture):
    pass

API Reference

@data_fixture(file_path, description="", loader=None)

Register a class or function as a data-driven fixture.

Parameter Type Description
file_path str Path to data file, relative to fingest_fixture_path
description str Optional label for debugging / docs
loader callable Optional custom loader (Path) → Any

register_loader(extension, loader_func)

Register a custom data loader globally for a file extension (without dot).

Base Classes

Class Key Methods
BaseFixture data, description, len(), bool(), iter(), in, ==
JSONFixture keys(), values(), items(), get(), length(), []
CSVFixture rows, row_count, columns, get_column(), filter_rows(), []
XMLFixture root, tag, find(), findall(), xpath(), get_text(), to_dict()

Development

git clone https://github.com/0x68/fingest.git
cd fingest
poetry install
poetry run pytest

License

MIT — see LICENSE.


Made with ❤️ by Tim Fiedler

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

fingest-1.0.4.tar.gz (136.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

fingest-1.0.4-py3-none-any.whl (15.1 kB view details)

Uploaded Python 3

File details

Details for the file fingest-1.0.4.tar.gz.

File metadata

  • Download URL: fingest-1.0.4.tar.gz
  • Upload date:
  • Size: 136.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for fingest-1.0.4.tar.gz
Algorithm Hash digest
SHA256 fde2ddf52c1dbaf7c0773e14ac9355a75d3c51fcd4ab1a2cd718b3be9eee199f
MD5 94e4540b7c4b997c2921863005a52ee0
BLAKE2b-256 e7efe06502f2032cdcb13c539934f53a7a4cee0f6f96e8be75c938a416bf480c

See more details on using hashes here.

Provenance

The following attestation bundles were made for fingest-1.0.4.tar.gz:

Publisher: workflow.yml on 0x68/fingest

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file fingest-1.0.4-py3-none-any.whl.

File metadata

  • Download URL: fingest-1.0.4-py3-none-any.whl
  • Upload date:
  • Size: 15.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for fingest-1.0.4-py3-none-any.whl
Algorithm Hash digest
SHA256 79f2353bf0fa264f59593cdcd2bfe06acaa0f25b1e8360aab3ddd63b420245a3
MD5 c6dc3066b04e9397be8564aa96206589
BLAKE2b-256 848aaa94baa66e928fe0d2f21a4e799f0e0147474004fd9603c5b01f46fd054f

See more details on using hashes here.

Provenance

The following attestation bundles were made for fingest-1.0.4-py3-none-any.whl:

Publisher: workflow.yml on 0x68/fingest

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page