Pytest fixtures¶
Polyfactory support registering factories as pytest fixtures using the
register_fixture
decorator:
Using the
register_fixture_decorator
field.¶from dataclasses import dataclass
from datetime import date, datetime
from typing import List, Optional, Union
from uuid import UUID
from polyfactory.factories import DataclassFactory
from polyfactory.pytest_plugin import register_fixture
@dataclass
class Person:
id: UUID
name: str
hobbies: Optional[List[str]]
nicks: List[str]
age: Union[float, int]
birthday: Union[datetime, date]
@register_fixture
class PersonFactory(DataclassFactory[Person]): ...
# NOTE: PersonFactory is no more a factory class, it is a callable that returns the decorated factory
def test_person_factory(person_factory: DataclassFactory[Person]) -> None:
person_instance = person_factory.build()
assert isinstance(person_instance, Person)
In the above example the PersonFactory
is wrapped as a pytest fixture. As a result it cannot be used as a normal
factory,because pytest fixtures are callables that must be called by pytest. To overcome this restriction, you can
declare the fixture separately from the declaration of the class:
Using the
register_fixture_decorator
field without wrapping the factory class.¶from dataclasses import dataclass
from datetime import date, datetime
from typing import List, Optional, Union
from uuid import UUID
from polyfactory.factories import DataclassFactory
from polyfactory.pytest_plugin import register_fixture
@dataclass
class Person:
id: UUID
name: str
hobbies: Optional[List[str]]
nicks: List[str]
age: Union[float, int]
birthday: Union[datetime, date]
class PersonFactory(DataclassFactory[Person]): ...
person_factory_fixture = register_fixture(PersonFactory)
def test_person_factory(person_factory: PersonFactory) -> None:
person_instance = person_factory.build()
assert isinstance(person_instance, Person)
# we can still access the factory class itself-
another_person_instance = PersonFactory.build()
assert isinstance(another_person_instance, Person)
You can also control the name of the fixture using the optional name
kwarg:
Aliasing a factory fixture using the name kwarg.¶
from dataclasses import dataclass
from datetime import date, datetime
from typing import List, Optional, Union
from uuid import UUID
from polyfactory.factories import DataclassFactory
from polyfactory.pytest_plugin import register_fixture
@dataclass
class Person:
id: UUID
name: str
hobbies: Optional[List[str]]
nicks: List[str]
age: Union[float, int]
birthday: Union[datetime, date]
class PersonFactory(DataclassFactory[Person]): ...
person_factory_fixture = register_fixture(PersonFactory, name="aliased_person_factory")
def test_person_factory(aliased_person_factory: PersonFactory) -> None:
person_instance = aliased_person_factory.build()
assert isinstance(person_instance, Person)
The Fixture
Field¶
You can also use factory fixtures as factory fields using the Fixture
:
Using the
Fixture
field.¶from dataclasses import dataclass
from datetime import date, datetime
from typing import List, Optional, Union
from uuid import UUID
from polyfactory import Fixture
from polyfactory.factories import DataclassFactory
from polyfactory.pytest_plugin import register_fixture
@dataclass
class Person:
id: UUID
name: str
hobbies: Optional[List[str]]
nicks: List[str]
age: Union[float, int]
birthday: Union[datetime, date]
@dataclass
class ClassRoom:
teacher: Person
pupils: List[Person]
@register_fixture
class PersonFactory(DataclassFactory[Person]): ...
class ClassRoomFactory(DataclassFactory[ClassRoom]):
teacher = Fixture(PersonFactory, name="Ludmilla Newman")
pupils = Fixture(PersonFactory, size=20)
def test_fixture_field() -> None:
classroom_instance = ClassRoomFactory.build()
assert isinstance(classroom_instance.teacher, Person)
assert classroom_instance.teacher.name == "Ludmilla Newman"
assert len(classroom_instance.pupils) == 20
Fixture
is similar to Use
in that it accepts kwargs that are propagated the to the build or batch methods of the
factory.