Skip to main content

No project description provided

Project description

pytest bonsai

Read the Docs

pytest-bonsai is a plugin that brings elegant, declarative, and composable test data to your test suite.

pytest-bonsai helps you grow minimal, yet expressive dependency trees using Python dataclasses, fixtures, and dynamic parameter resolution.

Installation

$ pip install pytest-bonsai

Showcase

import random
from dataclasses import dataclass, field
from enum import Enum

import pytest

from pytest_bonsai import FixtureRequest, expand, parametrized_fixture


class Rank(Enum):
    GENIN = "Genin"
    CHUNIN = "Chunin"
    JONIN = "Jonin"


class Weapon(Enum):
    KATANA = "Katana"
    KUSARIGAMA = "Kusarigama"
    NUNCHAKU = "Nunchaku"
    SHURIKEN = "Shuriken"
    TANTO = "Tanto"


@dataclass
class Uniform:
    emblem: str
    color: str


@dataclass
class Dojo:
    name: str
    weapons: list[Weapon]
    uniform: Uniform


@dataclass
class Ninja:
    name: str
    rank: Rank
    dojo: Dojo
    weapon: Weapon
    uniform: Uniform

    def __repr__(self):
        return (
            f"{self.name} {self.rank.value}, "
            f"armed with {self.weapon.value}, "
            f"wearing {self.uniform.color} uniform with {self.uniform.emblem}"
        )


# parametrized fixtures act as factories
@dataclass
class DojoParam:
    name: str = field(default_factory=lambda: random.choice(["Konoha", "Kiri", "Kumo"]))
    weapons: list[Weapon] = field(default_factory=lambda: random.sample(list(Weapon), 2))
    uniform_color: str = "black"


@parametrized_fixture(DojoParam)
def dojo(request: FixtureRequest[DojoParam]) -> Dojo:
    return Dojo(
        name=request.param.name,
        weapons=request.param.weapons,
        uniform=Uniform(emblem=f"emblem of {request.param.name}-ryu", color=request.param.uniform_color),
    )


@dataclass
class NinjaParam:
    name: str = field(default_factory=lambda: random.choice(["Hattori", "Goemon", "Kotarou"]))
    rank: Rank = field(default_factory=lambda: random.choice(list(Rank)))
    dojo: Dojo = field(default_factory=dojo)
    weapon: Weapon | None = None
    uniform: Uniform | None = None


@parametrized_fixture(NinjaParam)
def ninja(request: FixtureRequest[NinjaParam]) -> Ninja:
    return Ninja(
        name=request.param.name,
        rank=request.param.rank,
        dojo=request.param.dojo,
        weapon=request.param.weapon or random.choice(request.param.dojo.weapons),
        uniform=request.param.uniform or request.param.dojo.uniform,
    )


# by default, ninjas use dojo's uniform and weapon
def test_ninja_uses_approved_equipment(ninja, dojo):
    assert ninja.weapon in dojo.weapons
    assert ninja.uniform is dojo.uniform


# but can have personal preferences
@ninja.parametrize(weapon=Weapon.KATANA)
def test_sword_ninja(ninja, dojo):
    assert ninja.weapon == Weapon.KATANA


# some are allowed to wear special uniforms
@pytest.fixture
def red_uniform(dojo):
    return Uniform(emblem=dojo.uniform.emblem, color="red")


@ninja.parametrize(uniform=red_uniform)
def test_red_ninja(ninja, dojo):
    assert ninja.uniform.color == "red"


# or choose the color on the fly
@ninja.parametrize(uniform=lambda dojo: Uniform(emblem=dojo.uniform.emblem, color="green"))
def test_green_ninja(ninja, dojo):
    assert ninja.uniform.color == "green"


# some may even choose a diffrent uniform for each assignment
@parametrized_fixture
def color(request): ...


@ninja.parametrize(uniform=lambda dojo, color: Uniform(emblem=dojo.uniform.emblem, color=color))
@color.parametrize(expand(["blue", "pink"]))
def test_rainbow_ninja(ninja, dojo, color):
    assert ninja.uniform.color == color
    assert ninja.uniform.emblem == dojo.uniform.emblem
    assert ninja.weapon in dojo.weapons


# masters have the highest rank, but specialize in weapon of choice
@parametrized_fixture
def master_weapon(request): ...


@ninja.parametrize(rank=Rank.JONIN, weapon=master_weapon)
class TestMasters:
    @master_weapon.parametrize(Weapon.KATANA)
    def test_katana_master(self, ninja, master_weapon):
        assert ninja.rank == Rank.JONIN
        assert ninja.weapon == Weapon.KATANA

    @master_weapon.parametrize(Weapon.TANTO)
    def test_tanto_master(self, ninja, master_weapon):
        assert ninja.rank == Rank.JONIN
        assert ninja.weapon == Weapon.TANTO

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

pytest_bonsai-0.0.2.tar.gz (11.1 kB view details)

Uploaded Source

Built Distribution

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

pytest_bonsai-0.0.2-py3-none-any.whl (6.5 kB view details)

Uploaded Python 3

File details

Details for the file pytest_bonsai-0.0.2.tar.gz.

File metadata

  • Download URL: pytest_bonsai-0.0.2.tar.gz
  • Upload date:
  • Size: 11.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.12.9

File hashes

Hashes for pytest_bonsai-0.0.2.tar.gz
Algorithm Hash digest
SHA256 fc252f8d1402ef01db1de11d93a90651dbb5c4ba55ef97a556dda9dd24723233
MD5 88d2cd2fc6c655b3fb1af409f2dd7ce4
BLAKE2b-256 c30b8dc0459b4b6dd6987f0cc30d891b4750f870eb5d3994d0feab49afecc560

See more details on using hashes here.

Provenance

The following attestation bundles were made for pytest_bonsai-0.0.2.tar.gz:

Publisher: python-publish.yml on mrzechonek/pytest-bonsai

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

File details

Details for the file pytest_bonsai-0.0.2-py3-none-any.whl.

File metadata

  • Download URL: pytest_bonsai-0.0.2-py3-none-any.whl
  • Upload date:
  • Size: 6.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.12.9

File hashes

Hashes for pytest_bonsai-0.0.2-py3-none-any.whl
Algorithm Hash digest
SHA256 76784ed09cb038ba46f786aec4e17553b39d74cc68a3f82357cfe14d2ebb08ed
MD5 8772169198e2e012d8a0632d6c1c85c0
BLAKE2b-256 e528bfff3ae643b284c6ea4ad2bdd10c4ba780edc2c01181cd6f60c39fc5fed9

See more details on using hashes here.

Provenance

The following attestation bundles were made for pytest_bonsai-0.0.2-py3-none-any.whl:

Publisher: python-publish.yml on mrzechonek/pytest-bonsai

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