or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.md
tile.json

tessl/pypi-pytest-lazy-fixture

A pytest plugin that enables the use of fixtures within pytest.mark.parametrize decorators through lazy evaluation

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
pypipkg:pypi/pytest-lazy-fixture@0.6.x

To install, run

npx @tessl/cli install tessl/pypi-pytest-lazy-fixture@0.6.0

index.mddocs/

pytest-lazy-fixture

A pytest plugin that enables the use of fixtures within pytest.mark.parametrize decorators through lazy evaluation. This plugin solves the limitation where fixtures cannot normally be used directly in parametrize decorators by providing a lazy evaluation mechanism that resolves fixture values at test runtime.

Package Information

  • Package Name: pytest-lazy-fixture
  • Language: Python
  • Installation: pip install pytest-lazy-fixture
  • Requirements: pytest>=3.2.5

Core Imports

import pytest
# The plugin automatically makes lazy_fixture available via pytest namespace
pytest.lazy_fixture('fixture_name')

Direct import:

from pytest_lazyfixture import lazy_fixture, is_lazy_fixture, LazyFixture

Basic Usage

import pytest

# Define a fixture with parameters
@pytest.fixture(params=[1, 2])
def one(request):
    return request.param

# Use lazy_fixture in parametrize to reference the fixture
@pytest.mark.parametrize('arg1,arg2', [
    ('val1', pytest.lazy_fixture('one')),
    ('val2', pytest.lazy_fixture('one')),
])
def test_func(arg1, arg2):
    assert arg2 in [1, 2]

# Multiple lazy fixtures in one parametrize
@pytest.fixture(params=[3, 4])
def two(request):
    return request.param

@pytest.mark.parametrize('arg1,arg2,arg3', [
    ('val1', pytest.lazy_fixture('one'), pytest.lazy_fixture('two')),
])
def test_multiple(arg1, arg2, arg3):
    assert arg2 in [1, 2]
    assert arg3 in [3, 4]

# Use in fixture parameters (indirect parametrization)
@pytest.fixture(params=[
    pytest.lazy_fixture('one'),
    pytest.lazy_fixture('two')
])
def combined(request):
    return request.param

def test_combined(combined):
    assert combined in [1, 2, 3, 4]

Architecture

The pytest-lazy-fixture plugin uses pytest's hook system to intercept and modify test collection and execution. The core design enables lazy evaluation through several key components:

Hook Integration

  • pytest_configure(): Registers lazy_fixture function in pytest namespace for convenient access
  • pytest_runtest_setup(): Modifies test request object to handle lazy fixture resolution during setup
  • pytest_fixture_setup(): Resolves lazy fixtures used as parameters to other fixtures
  • pytest_generate_tests(): Normalizes test generation to expand lazy fixture combinations

Lazy Evaluation Mechanism

The plugin defers fixture resolution until test runtime rather than collection time:

  1. Collection Phase: LazyFixture objects store fixture names without resolving values
  2. Setup Phase: Plugin hooks intercept test setup and replace LazyFixture objects with actual fixture values
  3. Execution Phase: Tests receive fully resolved fixture values transparently

Dependency Resolution

  • Dependency Tracking: Analyzes fixture dependency chains to ensure correct resolution order
  • Parameter Expansion: Handles parametrized fixtures by expanding all combinations of lazy fixture values
  • Metafunction Modification: Modifies pytest's internal test generation to support lazy fixture combinations

This design allows fixtures to be used in @pytest.mark.parametrize decorators while maintaining pytest's normal fixture dependency resolution and scoping rules.

Capabilities

Lazy Fixture Creation

Creates lazy fixture references that are resolved at test runtime rather than collection time.

def lazy_fixture(names):
    """
    Create lazy fixture references for use in parametrize decorators.
    
    Args:
        names (str or list): Single fixture name or list of fixture names
        
    Returns:
        LazyFixture or list[LazyFixture]: Lazy fixture wrapper(s)
    """

Usage examples:

# Single fixture
lazy_ref = pytest.lazy_fixture('my_fixture') 

# Multiple fixtures
lazy_refs = lazy_fixture(['fixture1', 'fixture2'])

Lazy Fixture Detection

Utility function to check if a value is a lazy fixture instance.

def is_lazy_fixture(val):
    """
    Check if a value is a LazyFixture instance.
    
    Args:
        val: Value to check
        
    Returns:
        bool: True if val is a LazyFixture instance
    """

Usage example:

if is_lazy_fixture(some_value):
    # Handle lazy fixture
    actual_value = request.getfixturevalue(some_value.name)

Lazy Fixture Wrapper

The core wrapper class that holds fixture names for lazy evaluation.

class LazyFixture(object):
    """
    Wrapper class for lazy fixture evaluation.
    
    Attributes:
        name (str): Name of the fixture to be resolved
    """
    
    def __init__(self, name):
        """
        Initialize lazy fixture with fixture name.
        
        Args:
            name (str): Name of the fixture to wrap
        """
    
    def __repr__(self):
        """
        String representation of the lazy fixture.
        
        Returns:
            str: Formatted string showing class name and fixture name
        """
    
    def __eq__(self, other):
        """
        Compare LazyFixture instances by fixture name.
        
        Args:
            other (LazyFixture): Another LazyFixture instance
            
        Returns:
            bool: True if fixture names are equal
        """

Plugin Integration

The plugin automatically integrates with pytest through entry points and hooks:

# Available after plugin installation
pytest.lazy_fixture  # Function accessible via pytest namespace

Plugin Features

Parametrize Integration

  • Direct parametrization: Use lazy fixtures as parameter values in @pytest.mark.parametrize
  • Multiple fixtures: Support for multiple lazy fixtures in the same parametrize decorator
  • Mixed parameters: Combine lazy fixtures with regular values in parametrize

Indirect Parametrization

  • Fixture parameters: Use lazy fixtures as parameters to other fixtures
  • Fixture chains: Support for fixtures that depend on other fixtures through lazy evaluation

Test ID Generation

  • Automatic naming: Test IDs automatically use fixture names for lazy fixtures
  • Clear identification: Easy identification of which fixture values are being tested

Dependency Resolution

  • Automatic resolution: Lazy fixtures are resolved automatically at test runtime
  • Dependency order: Proper handling of fixture dependency chains
  • Parameter sorting: Internal sorting to ensure fixtures are resolved in correct order

Internal Implementation Details

The plugin works by:

  1. Hook Integration: Registers pytest hooks to intercept test collection and execution
  2. Lazy Evaluation: Defers fixture resolution until test runtime using request.getfixturevalue()
  3. Metafunction Modification: Modifies pytest's metafunction calls to handle lazy fixtures
  4. Dependency Tracking: Tracks and resolves fixture dependencies in correct order

Key internal functions (not part of public API):

  • pytest_runtest_setup(): Modifies test setup to handle lazy fixtures
  • pytest_fixture_setup(): Resolves lazy fixtures used as fixture parameters
  • pytest_generate_tests(): Normalizes test generation for lazy fixtures
  • sorted_by_dependency(): Ensures fixtures are resolved in dependency order

Error Handling

The plugin handles various pytest version compatibility issues and provides appropriate error handling for:

  • Missing fixtures referenced by lazy_fixture
  • Circular fixture dependencies
  • Version compatibility across pytest 3.2.5+ releases

Compatibility

  • Python: 2.7, 3.4+
  • pytest: 3.2.5+
  • Platforms: Cross-platform (Windows, macOS, Linux)
  • Implementation: CPython, PyPy