pytest-lazy-fixtures1.4.0
Published
Allows you to use fixtures in @pytest.mark.parametrize.
pip install pytest-lazy-fixtures
Package Downloads
Authors
Project URLs
Requires Python
>=3.8
Dependencies
pytest-lazy-fixtures
Use your fixtures in @pytest.mark.parametrize
.
This project was inspired by pytest-lazy-fixture.
Improvements that have been made in this project:
- You can use fixtures in any data structures
- You can access the attributes of fixtures
- You can use functions in fixtures
- It is compatible with pytest-deadfixtures
Installation
pip install pytest-lazy-fixtures
Usage
To use your fixtures inside @pytest.mark.parametrize
you can use lf
(lazy_fixture
).
import pytest
from pytest_lazy_fixtures import lf
@pytest.fixture()
def one():
return 1
@pytest.mark.parametrize('arg1,arg2', [('val1', lf('one'))])
def test_func(arg1, arg2):
assert arg2 == 1
lf
can be used with any data structures. For example, in the following example, lf
is used in the dictionary:
import pytest
from pytest_lazy_fixtures import lf
@pytest.fixture()
def one():
return 1
@pytest.mark.parametrize('arg1,arg2', [('val1', {"value": lf('one')})])
def test_func(arg1, arg2):
assert arg2 == {"value": 1}
You can also specify getting an attribute through a dot:
import pytest
from pytest_lazy_fixtures import lf
class Entity:
def __init__(self, value):
self.value = value
@pytest.fixture()
def one():
return Entity(1)
@pytest.mark.parametrize('arg1,arg2', [('val1', lf('one.value'))])
def test_func(arg1, arg2):
assert arg2 == 1
And there is some useful wrapper called lfc
(lazy_fixture_callable
).
It can work with any callable and your fixtures.
import pytest
from pytest_lazy_fixtures import lf, lfc
class Entity:
def __init__(self, value):
self.value = value
def __str__(self) -> str:
return str(self.value)
def sum(self, value: int) -> int:
return self.value + value
@pytest.fixture()
def entity():
return Entity(1)
@pytest.fixture()
def two():
return 2
@pytest.fixture()
def three():
return 3
@pytest.fixture()
def entity_format():
def _entity_format(entity: Entity):
return {"value": entity.value}
return _entity_format
# Recommended: implicit injection from the callable's parameter names
@pytest.mark.parametrize("as_text", [lfc(lambda entity: str(entity))])
def test_lfc_injection_basic(as_text):
assert as_text == "1"
# Advanced: manual control over what to inject (explicit values into a callable)
@pytest.mark.parametrize(
"message",
[
lfc(
"There is two lazy fixture args, {} and {}! And one kwarg {field}! And also simple value {simple}".format,
lf("entity"),
lf("two"),
field=lf("three"),
simple="value",
),
],
)
def test_lazy_fixture_callable_with_func(message):
assert message == "There is two lazy fixture args, 1 and 2! And one kwarg 3! And also simple value value"
@pytest.mark.parametrize("formatted", [lfc("entity_format", lf("entity"))])
def test_lazy_fixture_callable_with_lf(formatted, entity):
assert formatted == {"value": entity.value}
@pytest.mark.parametrize("result", [lfc("entity.sum", lf("two"))])
def test_lazy_fixture_callable_with_attr_lf(result):
assert result == 3
Injecting fixtures from a callable signature
lfc
automatically injects fixtures based on the callable's parameter names. If a parameter name matches a fixture name, that fixture will be resolved and passed into the callable. This implicit injection is the standard, recommended behavior. You can still override any parameter explicitly using lf
, either positionally or by name.
Default values prevent implicit injection for that parameter.
Examples:
import pytest
from pytest_lazy_fixtures import lf, lfc
# Some fixtures used in the examples
@pytest.fixture()
def alpha():
return 10
@pytest.fixture()
def beta():
return 20
@pytest.fixture()
def gamma():
return 30
# Simple implicit injection by parameter name
@pytest.mark.parametrize("result", [lfc(lambda alpha: alpha + 1)])
def test_signature_injection_basic(result):
assert result == 11
# Override an implicitly matched parameter (positional or keyword)
@pytest.mark.parametrize(
"result",
[
lfc(lambda alpha: alpha + 1, lf("beta")), # positional override
lfc(lambda alpha: alpha + 1, alpha=lf("beta")), # keyword override
],
)
def test_signature_injection_override(result):
assert result == 21
# Mix implicit and explicit params
@pytest.mark.parametrize(
"pair",
[
lfc(lambda alpha, beta: (alpha, beta), beta=lf("gamma")), # first implicit, second explicit
lfc(lambda alpha, beta: (alpha, beta), lf("gamma")), # first explicit, second implicit
],
)
def test_signature_injection_mixed(pair):
assert pair in [(10, 30), (30, 20)]
# 4) Defaults prevent implicit injection for that parameter
@pytest.mark.parametrize("val", [lfc(lambda alpha=999: alpha)])
def test_signature_injection_defaults(val):
assert val == 999
Notes:
- Implicit injection only happens for parameters without an explicit value and without a default.
- Explicit arguments passed to
lfc
(positional or keyword) always take precedence over implicit injection. - The mapping of positional explicit arguments follows the callable's parameter order.
Contributing
Contributions are very welcome. Tests can be run with pytest
.
License
Distributed under the terms of the MIT
license, pytest-lazy-fixtures
is free and open source software
Issues
If you encounter any problems, please file an issue along with a detailed description.