Faker and polyfactory seeded Pydantic model factories offline: working versions (tested 2026-10-16)
Define Pydantic models and generate fixtures offline with polyfactory, binding one Faker instance so Use() providers and seed_random stay reproducible.
passed6 passed · 0 failed2026-10-16 00:01 UTC- Status
- passed
- Last passed
- 2026-10-16 00:01 UTC
- Tests
- 6 / 6
- Language
- Python
- Runtime
- Python 3.13.16
uv venv -q .venv && uv pip install -q --python .venv/bin/python -r requirements.txt .venv/bin/python -m pytest -q
Python 3.13.16 linux 6.17.0-1022-azure x64 runner: github-actions 38826982604
The code
Exactly the files that passed. Your agent can pull them with get_recipe("faker-polyfactory-seeded") (install), or see them on GitHub.
faker==40.43.0 polyfactory==3.3.0 pydantic==2.14.1 pytest==9.1.1
from typing import Annotated, Literal
from faker import Faker
from polyfactory import Use
from polyfactory.factories.pydantic_factory import ModelFactory
from pydantic import BaseModel, Field
class Address(BaseModel):
city: str
country_code: Annotated[str, Field(pattern=r"^[A-Z]{2}$")]
class Customer(BaseModel):
id: int
email: str
age: int = Field(ge=18, le=99)
plan: Literal["free", "pro"]
address: Address
class CustomerFactory(ModelFactory[Customer]):
# no __faker__ of its own, so it inherits the Faker shared by every factory
__model__ = Customer
_fake = Faker()
class SeededCustomerFactory(ModelFactory[Customer]):
# bind one Faker instance so seed_random() and Use() drive the same generator
__model__ = Customer
__faker__ = _fake
email = Use(_fake.email)
def reseed(factory: type[ModelFactory[Customer]], seed: int) -> type[ModelFactory[Customer]]:
factory.seed_random(seed)
return factory
import pytest
from pydantic import ValidationError
from factories import (
Customer,
CustomerFactory,
ModelFactory,
SeededCustomerFactory,
reseed,
)
def test_type_generation_ignores_field_names():
reseed(CustomerFactory, 1)
assert "@" not in CustomerFactory.build().email # str becomes pystr(), not an email
reseed(SeededCustomerFactory, 1)
assert "@" in SeededCustomerFactory.build().email # Use(fake.email) instead
def test_seed_random_makes_batches_repeatable():
first = [c.model_dump() for c in reseed(SeededCustomerFactory, 1234).batch(3)]
second = [c.model_dump() for c in reseed(SeededCustomerFactory, 1234).batch(3)]
assert first == second
def test_batch_resumes_the_faker_stream_without_a_reseed():
reseed(SeededCustomerFactory, 7)
a = SeededCustomerFactory.build().email
b = SeededCustomerFactory.build().email
assert a != b # __random_seed__ only fires once, when the class is created
def test_field_constraints_are_enforced_while_generating():
for customer in reseed(SeededCustomerFactory, 99).batch(25):
assert 18 <= customer.age <= 99
assert customer.plan in {"free", "pro"}
assert len(customer.address.country_code) == 2
assert customer.address.country_code.isupper()
def test_construct_build_bypasses_validation():
with pytest.raises(ValidationError):
SeededCustomerFactory.build(age=10)
invalid = SeededCustomerFactory.build(factory_use_construct=True, age=10)
assert invalid.age == 10 # model_construct() skips the ge=18 constraint
def test_default_faker_is_shared_so_seeding_leaks():
other = ModelFactory.create_factory(Customer)
assert other.__faker__ is CustomerFactory.__faker__
a = [c.model_dump() for c in reseed(CustomerFactory, 11).batch(2)]
b = [c.model_dump() for c in reseed(other, 11).batch(2)]
assert a == b # both draw from BaseFactory's single Faker instance
assert SeededCustomerFactory.__faker__ is not CustomerFactory.__faker__
[pytest] pythonpath = .
Connect to ProvenPin
Add the free MCP server so your agent can pull this recipe and others like it. Same setup as the docs.
claude mcp add --transport http provenpin https://mcp.provenpin.com/mcp
{ "mcpServers": { "provenpin": { "url": "https://mcp.provenpin.com/mcp" } } }{ "servers": { "provenpin": { "type": "http", "url": "https://mcp.provenpin.com/mcp" } } }{ "mcpServers": { "provenpin": { "serverUrl": "https://mcp.provenpin.com/mcp" } } }{ "mcpServers": { "provenpin": { "type": "streamableHttp", "url": "https://mcp.provenpin.com/mcp" } } }Any other MCP client: Streamable HTTP at https://mcp.provenpin.com/mcp. No API key, no signup.
Related stacks
Generate Hypothesis strategies from polyfactory pydantic models
Bridge a polyfactory ModelFactory into Hypothesis: regex strings, HttpUrl and other pydantic-core types come from the factory while the fields under test stay drawable and shrinkable.
beartype conf + pydantic model_validate runtime checks
Pair beartype boundary checks with pydantic model_validate, using BeartypeConf to align int/float coercion and route violations, and pin down the gotchas where the two guards disagree.
DeepDiff diffing of pydantic v2 model dumps with ignore_order
Compare pydantic v2 model dumps with DeepDiff, normalizing python vs json dump modes and taming list order, datetime and float gotchas.
FastAPI + Pydantic v2 validators, discriminated unions and serializers
Pydantic v2 patterns in FastAPI that agents often get wrong: field_validator, model_validator, discriminated unions, computed_field and response_model filtering.
All faker recipesAll polyfactory recipesAll Pydantic recipes