В этом руководстве мы подробно рассмотрим продвинутое использование Polyfactory, сосредоточив внимание на том, как можно генерировать богатые и реалистичные фиктивные данные непосредственно из подсказок типов Python.
Установка среды и зависимостей
Мы начнём с настройки среды и постепенно создадим фабрики для классов данных, моделей Pydantic и классов на основе attrs, демонстрируя настройку, переопределения, вычисляемые поля и генерацию вложенных объектов.
«`python
import subprocess
import sys
def install_package(package):
subprocess.check_call([sys.executable, «-m», «pip», «install», «-q», package])
packages = [
«polyfactory»,
«pydantic»,
«email-validator»,
«faker»,
«msgspec»,
«attrs»
]
for package in packages:
try:
install_package(package)
print(f»✓ Installed {package}»)
except Exception as e:
print(f»✗ Failed to install {package}: {e}»)
print(«\n»)
print(«=» * 80)
print(«SECTION 2: Basic Dataclass Factories»)
print(«=» * 80)
«`
Основные фабрики классов данных
Мы настроили среду и убедились, что все необходимые зависимости установлены. Также мы познакомили вас с основной идеей использования Polyfactory для генерации фиктивных данных из подсказок типов.
«`python
from dataclasses import dataclass
from typing import List, Optional
from datetime import datetime, date
from uuid import UUID
from polyfactory.factories import DataclassFactory
@dataclass
class Address:
street: str
city: str
country: str
zip_code: str
@dataclass
class Person:
id: UUID
name: str
email: str
age: int
birth_date: date
is_active: bool
address: Address
phone_numbers: List[str]
bio: Optional[str] = None
class PersonFactory(DataclassFactory[Person]):
pass
person = PersonFactory.build()
print(f»Generated Person:»)
print(f» ID: {person.id}»)
print(f» Name: {person.name}»)
print(f» Email: {person.email}»)
print(f» Age: {person.age}»)
print(f» Address: {person.address.city}, {person.address.country}»)
print(f» Phone Numbers: {person.phone_numbers[:2]}»)
print()
«`
Настройка поведения фабрики
Мы сосредоточились на генерации простых, но реалистичных фиктивных данных, используя классы данных и поведение Polyfactory по умолчанию.
«`python
from faker import Faker
from polyfactory.fields import Use, Ignore
@dataclass
class Employee:
employee_id: str
full_name: str
department: str
salary: float
hire_date: date
is_manager: bool
email: str
internal_notes: Optional[str] = None
class EmployeeFactory(DataclassFactory[Employee]):
faker = Faker(locale=»en_US»)
random_seed = 42
@classmethod
def employee_id(cls) -> str:
return f»EMP-{cls.random.randint(10000, 99999)}»
@classmethod
def full_name(cls) -> str:
return cls.faker.name()
@classmethod
def department(cls) -> str:
departments = [«Engineering», «Marketing», «Sales», «HR», «Finance»]
return cls.random.choice(departments)
@classmethod
def salary(cls) -> float:
return round(cls.random.uniform(50000, 150000), 2)
@classmethod
def email(cls) -> str:
return cls.faker.company_email()
«`
Ограничения полей и вычисляемые поля
Мы продемонстрировали, как можно быстро создавать отдельные экземпляры и пакеты без написания какой-либо пользовательской логики.
«`python
@dataclass
class Product:
product_id: str
name: str
description: str
price: float
discount_percentage: float
stock_quantity: int
final_price: Optional[float] = None
sku: Optional[str] = None
class ProductFactory(DataclassFactory[Product]):
@classmethod
def product_id(cls) -> str:
return f»PROD-{cls.random.randint(1000, 9999)}»
@classmethod
def name(cls) -> str:
adjectives = [«Premium», «Deluxe», «Classic», «Modern», «Eco»]
nouns = [«Widget», «Gadget», «Device», «Tool», «Appliance»]
return f»{cls.random.choice(adjectives)} {cls.random.choice(nouns)}»
@classmethod
def price(cls) -> float:
return round(cls.random.uniform(10.0, 1000.0), 2)
@classmethod
def discount_percentage(cls) -> float:
return round(cls.random.uniform(0, 30), 2)
@classmethod
def stock_quantity(cls) -> int:
return cls.random.randint(0, 500)
«`
Комплексные вложенные структуры
Мы построили более сложную логику предметной области, введя вычисляемые и зависимые поля внутри фабрик.
«`python
from enum import Enum
class OrderStatus(str, Enum):
PENDING = «pending»
PROCESSING = «processing»
SHIPPED = «shipped»
DELIVERED = «delivered»
CANCELLED = «cancelled»
@dataclass
class OrderItem:
product_name: str
quantity: int
unit_price: float
total_price: Optional[float] = None
@dataclass
class ShippingInfo:
carrier: str
tracking_number: str
estimated_delivery: date
@dataclass
class Order:
order_id: str
customer_name: str
customer_email: str
status: OrderStatus
items: List[OrderItem]
order_date: datetime
shipping_info: Optional[ShippingInfo] = None
total_amount: Optional[float] = None
notes: Optional[str] = None
«`
Интеграция с Attrs
Мы расширили использование Polyfactory для проверенных моделей Pydantic и классов на основе attrs.
«`python
import attrs
from polyfactory.factories.attrs_factory import AttrsFactory
@attrs.define
class BlogPost:
title: str
author: str
content: str
views: int = 0
likes: int = 0
published: bool = False
published_at: Optional[datetime] = None
tags: List[str] = attrs.field(factory=list)
class BlogPostFactory(AttrsFactory[BlogPost]):
@classmethod
def title(cls) -> str:
templates = [
«10 Tips for {}»,
«Understanding {}»,
«The Complete Guide to {}»,
«Why {} Matters»,
«Getting Started with {}»
]
topics = [«Python», «Data Science», «Machine Learning», «Web Development», «DevOps»]
template = cls.random.choice(templates)
topic = cls.random.choice(topics)
return template.format(topic)
«`
Построение с конкретными переопределениями
Мы продемонстрировали, как можно уважать ограничения полей, валидаторы и поведение по умолчанию, одновременно генерируя допустимые данные в масштабе.
«`python
custom_person = PersonFactory.build(
name=»Alice Johnson»,
age=30,
email=»alice@example.com»
)
print(f»Custom Person:»)
print(f» Name: {custom_person.name}»)
print(f» Age: {custom_person.age}»)
print(f» Email: {custom_person.email}»)
print(f» ID (auto-generated): {custom_person.id}»)
print()
«`
Контроль на уровне полей с использованием Use и Ignore
Мы продемонстрировали, как можно явно контролировать отдельные поля, используя Use и Ignore.
«`python
from polyfactory.fields import Use, Ignore
@dataclass
class Configuration:
app_name: str
version: str
debug: bool
created_at: datetime
api_key: str
secret_key: str
class ConfigFactory(DataclassFactory[Configuration]):
app_name = Use(lambda: «MyAwesomeApp»)
version = Use(lambda: «1.0.0»)
debug = Use(lambda: False)
@classmethod
def api_key(cls) -> str:
return f»apikey{».join(cls.random.choices(‘0123456789abcdef’, k=32))}»
@classmethod
def secret_key(cls) -> str:
return f»secret_{».join(cls.random.choices(‘0123456789abcdef’, k=64))}»
«`
Тестирование покрытия модели
Мы рассмотрели передовые шаблоны использования, такие как явные переопределения, постоянные значения полей и сценарии тестирования покрытия.
«`python
from pydantic import BaseModel, ConfigDict
from typing import Union
class PaymentMethod(BaseModel):
modelconfig = ConfigDict(useenum_values=True)
type: str
card_number: Optional[str] = None
bank_name: Optional[str] = None
verified: bool = False
class PaymentMethodFactory(ModelFactory[PaymentMethod]):
model = PaymentMethod
payment_methods = [
PaymentMethodFactory.build(type=»card», card_number=»4111111111111111″),
PaymentMethodFactory.build(type=»bank», bank_name=»Chase Bank»),
PaymentMethodFactory.build(verified=True),
]
«`
Резюме
В этом руководстве мы рассмотрели:
- Базовые фабрики классов данных.
- Настраиваемые генераторы полей.
- Ограничения полей.
- Интеграцию с Pydantic.
- Комплексные вложенные структуры.
- Поддержку Attrs.
- Построение с переопределениями.
- Контроль на уровне полей с использованием Use и Ignore.
- Тестирование покрытия.
Ключевые выводы:
- Polyfactory автоматически генерирует фиктивные данные из подсказок типов.
- Настройте генерацию с помощью методов класса и декораторов.
- Поддерживает несколько библиотек: dataclasses, Pydantic, attrs, msgspec.
- Используйте PostGenerated для вычисляемых/зависимых полей.
- Переопределяйте конкретные значения, сохраняя остальные случайными.
- Идеально подходит для тестирования, разработки и прототипирования.
1. Какие библиотеки используются вместе с Polyfactory для генерации фиктивных данных?
В статье упоминается использование нескольких библиотек вместе с Polyfactory для генерации фиктивных данных. Среди них: dataclasses, Pydantic, attrs, msgspec.
2. Какие преимущества даёт использование Polyfactory для генерации фиктивных данных?
Polyfactory позволяет автоматически генерировать фиктивные данные из подсказок типов. Это упрощает процесс создания тестовых данных и делает его более эффективным. Кроме того, Polyfactory поддерживает настройку генерации с помощью методов класса и декораторов, что позволяет адаптировать генерацию под конкретные потребности.
3. Какие методы используются для настройки поведения фабрики в Polyfactory?
Для настройки поведения фабрики в Polyfactory используются методы класса и декораторы. В статье приводятся примеры использования методов класса для определения поведения фабрики при генерации данных, например, для генерации идентификаторов сотрудников или их имён.
4. Какие типы данных можно генерировать с помощью Polyfactory?
С помощью Polyfactory можно генерировать различные типы данных, включая строки, числа, даты и другие. В статье приводятся примеры генерации идентификаторов, имён, адресов, телефонных номеров и других данных.
5. Какие возможности Polyfactory можно использовать для тестирования покрытия модели?
Polyfactory можно использовать для тестирования покрытия модели, генерируя различные комбинации данных и проверяя, как модель обрабатывает эти данные. В статье упоминается использование Polyfactory для генерации данных для тестирования покрытия модели PaymentMethod.