-
-
Notifications
You must be signed in to change notification settings - Fork 81
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(type-coverage-generation): model type coverage batch generation (#…
…390) Co-authored-by: Jacob Coffee <jacob@z7x.org> Co-authored-by: Andrew Truong <40660973+adhtruong@users.noreply.github.com> Co-authored-by: guacs <126393040+guacs@users.noreply.github.com>
- Loading branch information
1 parent
70d49fd
commit b1e8b5e
Showing
10 changed files
with
720 additions
and
19 deletions.
There are no files selected for viewing
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
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]): | ||
__model__ = 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) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
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]): | ||
__model__ = 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) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,3 +12,4 @@ Usage Guide | |
decorators | ||
fixtures | ||
handling_custom_types | ||
model_coverage |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
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: | ||
|
||
.. literalinclude:: /examples/model_coverage/test_example_1.py | ||
:caption: Defining a factory and generating examples with coverage | ||
:language: python | ||
|
||
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: | ||
|
||
.. literalinclude:: /examples/model_coverage/test_example_2.py | ||
:caption: Coverage output for the SocialGroup model | ||
:language: python | ||
|
||
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. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.