diff --git a/src/pytest_factoryboy/fixture.py b/src/pytest_factoryboy/fixture.py index d924c76..33d7a1f 100644 --- a/src/pytest_factoryboy/fixture.py +++ b/src/pytest_factoryboy/fixture.py @@ -27,7 +27,7 @@ ) from typing_extensions import ParamSpec -from .compat import PostGenerationContext +from .compat import PostGenerationContext, PytestFixtureT from .fixturegen import create_fixture if TYPE_CHECKING: @@ -172,16 +172,18 @@ def generate_fixtures( ), ) + deps = get_deps(factory_class, model_name=model_name) if factory_name not in caller_locals.value: yield ( factory_name, create_fixture_with_related( name=factory_name, function=functools.partial(factory_fixture, factory_class=factory_class), + fixtures=deps, + # TODO: related too? ), ) - deps = get_deps(factory_class, model_name=model_name) yield ( model_name, create_fixture_with_related( @@ -195,10 +197,10 @@ def generate_fixtures( def create_fixture_with_related( name: str, - function: Callable[P, T], + function: Callable[..., object], fixtures: Collection[str] | None = None, related: Collection[str] | None = None, -) -> Callable[P, T]: +) -> PytestFixtureT: if related is None: related = [] fixture, fn = create_fixture(name=name, function=function, fixtures=fixtures) @@ -366,6 +368,7 @@ def model_fixture(request: SubRequest, factory_name: str) -> object: fixture_name = request.fixturename prefix = "".join((fixture_name, SEPARATOR)) + # TODO: This should be a dependency of the current fixture (i.e. use `usefixtures`) factory_class: type[Factory[object]] = request.getfixturevalue(factory_name) # create Factory override for the model fixture @@ -500,7 +503,20 @@ def deferred_impl(request: SubRequest) -> object: def factory_fixture(request: SubRequest, factory_class: type[Factory[T]]) -> type[Factory[T]]: """Factory fixture implementation.""" - return factory_class + fixture_name = request.fixturename + # TODO: Not good to check the fixture name, we should know what to expect (via args?) + assert fixture_name.endswith("_factory") + fixture_name = fixture_name[: -len("_factory")] + prefix = "".join((fixture_name, SEPARATOR)) + + # TODO: copy-paste from model_fixture; refactor + kwargs = {} + for key in factory_class._meta.pre_declarations: + argname = "".join((prefix, key)) + if argname in request._fixturedef.argnames: + kwargs[key] = evaluate(request, request.getfixturevalue(argname)) + + return type(f"{factory_class.__name__}Fixture", (factory_class,), kwargs) def attr_fixture(request: SubRequest, value: T) -> T: diff --git a/tests/test_factory_fixtures.py b/tests/test_factory_fixtures.py index 3a35b9c..eddc990 100644 --- a/tests/test_factory_fixtures.py +++ b/tests/test_factory_fixtures.py @@ -109,7 +109,7 @@ class Meta: def test_factory(book_factory) -> None: """Test model factory fixture.""" - assert book_factory == BookFactory + assert issubclass(book_factory, BookFactory) def test_model(book: Book): diff --git a/tests/test_foo.py b/tests/test_foo.py new file mode 100644 index 0000000..657f9d2 --- /dev/null +++ b/tests/test_foo.py @@ -0,0 +1,30 @@ +# TODO: Improve tests +# TODO: Change test module + +from dataclasses import dataclass + +import factory +import pytest + +from pytest_factoryboy import register + + +@dataclass +class Book: + name: str + + +@register +class BookFactory(factory.Factory): + class Meta: + model = Book + + name = "foo" + + +@pytest.mark.parametrize("book__name", ["bar"]) +def test_book_initialise_later(book_factory, book__name, book): + assert book.name == "bar" + + book_f = book_factory() + assert book_f.name == "bar"