-
-
Notifications
You must be signed in to change notification settings - Fork 106
feat(type-coverage-generation): Model type coverage batch generation #390
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
42 commits
Select commit
Hold shift + click to select a range
d689ce0
feat(type-coverage-gen): Initial implementation of type coverage gene…
sam-or 84c9c51
fix: revert change to .pre-commit-config.yaml
sam-or e97b1c1
fix: Update NoneType importing for older python versions
sam-or 8df692f
fix: apply sourcery refactor
sam-or 9734172
fix: import ParamSpec from typing_extensions
sam-or 373fea4
fix: Skip tests on py versions < 3.10
sam-or ae38e54
fix: revert changes to .pre-commit-config.yaml
sam-or 1fb0608
chore: Create devcontainer.json
sam-or f2289d0
fix: remove .devcontainer dir
sam-or d9adc27
fix: Add missing test skip for older python versions
sam-or 20f4813
test: Add test for post generated in coverage generation
sam-or 176689a
Merge remote-tracking branch 'upstream/main' into coverage
sam-or 7f71339
test: Simplify type coverage generation tests
sam-or f93a498
test: Add back min python3.10 version condition
sam-or e306abc
fix(infra): update makefile (#399)
JacobCoffee 8752b81
docs: Install all dependencies for docs build (#404)
adhtruong f84b771
fix: decouple the handling of collection length configuration from `F…
vkcku 8a3ac1f
refactor: refactor the msgspec factory to use the fields API (#409)
vkcku 5baf00a
chore: prepare for releasing v2.10 (#410)
vkcku 7570acd
feat(type-coverage-gen): Initial implementation of type coverage gene…
sam-or 87df742
fix: Update NoneType importing for older python versions
sam-or 811658b
fix: Make CoverageContainer generic
sam-or bac1971
fix: linting and rebase issues
sam-or 2c0a71a
Merge remote-tracking branch 'upstream/main' into coverage
sam-or deb72a1
fix: revert pre-commit conf change
sam-or 85e2525
docs(type-coverage-gen): Add docs for coverage gen
sam-or 88923de
docs: Fix formatting in coverage docs
sam-or 006307d
Merge branch 'main' into coverage
sam-or a304a99
Merge branch 'main' into coverage
sam-or 2df1a26
docs: Move profile coverage exmaple into test func
sam-or f989775
docs: Update social group example to use test func
sam-or b337bc0
fix: Address review comments
sam-or be5e712
test: Remove 3.10 requirement for coverage tests
sam-or eb075e0
test: Move CustomInt definition outside of test
sam-or 5299535
test: disable ruff UP006 in test file
sam-or 93f8658
test: fix social group test in docs example
sam-or d70c526
test: fix social group test in doc example
sam-or d6e2ce8
test: Change hint dict to Dict in coverage test
sam-or d0cf706
test: Fix tuple annotation in coverage tests
sam-or 3201015
Merge branch 'main' into coverage
sam-or ba355e5
chore: fix formatting in docstring
sam-or 9c84551
chore: Add docstring to CoverageContainerCallable
sam-or File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Empty file.
This file contains hidden or 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 hidden or 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 hidden or 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 hidden or 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 hidden or 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 hidden or 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.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.