# Model coverage generation

The `BaseFactory.coverage()` function is an alternative approach to `BaseFactory.batch()`, where the examples that are generated attempt to provide full coverage of all the forms a model can take with the minimum number of instances. For example:

Defining a factory and generating examples with coverage

    from __future__ import annotations

    from dataclasses import dataclass
    from typing import Literal

    from polyfactory.factories.dataclass_factory import DataclassFactory

    @dataclass
    class Car:
        model: str

    @dataclass
    class Boat:
        can_float: bool

    @dataclass
    class Profile:
        age: int
        favourite_color: Literal["red", "green", "blue"]
        vehicle: Car | Boat

    class ProfileFactory(DataclassFactory[Profile]): ...

    def test_profile_coverage() -> None:
        profiles = list(ProfileFactory.coverage())

        assert profiles[0].favourite_color == "red"
        assert isinstance(profiles[0].vehicle, Car)
        assert profiles[1].favourite_color == "green"
        assert isinstance(profiles[1].vehicle, Boat)
        assert profiles[2].favourite_color == "blue"
        assert isinstance(profiles[2].vehicle, Car)

As you can see in the above example, the `Profile` model has 3 options for `favourite_color`, and 2 options for `vehicle`. In the output you can expect to see instances of `Profile` that have each of these options. The largest variance dictates the length of the output, in this case `favourite_color` has the most, at 3 options, so expect to see 3 `Profile` instances.

Note

Notice that the same `Car` instance is used in the first and final generated example. When the coverage examples for a field are exhausted before another field, values for that field are re-used.

## Notes on collection types

When generating coverage for models with fields that are collections, in particular collections that contain sub-models, the contents of the collection will be the all coverage examples for that sub-model. For example:

Coverage output for the SocialGroup model

    from __future__ import annotations

    from dataclasses import dataclass
    from typing import Literal

    from polyfactory.factories.dataclass_factory import DataclassFactory

    @dataclass
    class Car:
        model: str

    @dataclass
    class Boat:
        can_float: bool

    @dataclass
    class Profile:
        age: int
        favourite_color: Literal["red", "green", "blue"]
        vehicle: Car | Boat

    @dataclass
    class SocialGroup:
        members: list[Profile]

    class SocialGroupFactory(DataclassFactory[SocialGroup]): ...

    def test_social_group_coverage() -> None:
        groups = list(SocialGroupFactory.coverage())
        assert len(groups) == 3

        for group in groups:
            assert len(group.members) == 1

        assert groups[0].members[0].favourite_color == "red"
        assert isinstance(groups[0].members[0].vehicle, Car)
        assert groups[1].members[0].favourite_color == "green"
        assert isinstance(groups[1].members[0].vehicle, Boat)
        assert groups[2].members[0].favourite_color == "blue"
        assert isinstance(groups[2].members[0].vehicle, Car)

## Known Limitations

- Recursive models will cause an error: `RecursionError: maximum recursion depth exceeded`.

- `__min_collection_length__` and `__max_collection_length__` are currently ignored in coverage generation.