Faker и Pydantic в Python: генерация и валидация тестовых данных

Faker и Pydantic в Python: генерация и валидация тестовых данных Полезное

Faker и Pydantic — это две библиотеки Python, которые решают противоположные задачи и потому часто работают в паре: Faker генерирует реалистичные фейковые данные (имена, адреса, email), а Pydantic валидирует и парсит данные по описанной схеме. Ниже разберу каждую по отдельности на минимальных примерах с реальным выводом, а потом соберу связку: сгенерировать данные Faker и проверить их моделью Pydantic.

Все примеры прогонялись на Faker 37.x и Pydantic 2.x (сентябрь 2026). Синтаксис Pydantic дан под версию 2.x — в версии 1.x часть имен другая, об этом отдельно ниже.

Кто за что отвечает: Faker против Pydantic

Библиотеки легко перепутать, потому что обе крутятся вокруг «тестовых данных». Но направление у них разное: одна данные создает, другая — проверяет уже готовые.

Библиотека Что делает Ключевой объект Направление данных
Faker генерирует фейковые данные Faker() + провайдеры создает данные «из ничего»
Pydantic валидирует и парсит по схеме класс-наследник BaseModel проверяет данные на входе

Простой признак, по какому выбирать: нужно наполнить тест или базу правдоподобными значениями — берете Faker; нужно гарантировать, что пришедшие данные соответствуют типам и правилам — берете Pydantic. В связке Faker стоит на входе (источник), Pydantic — на контроле (фильтр).

Faker: генерация фейковых данных

Faker — библиотека для генерации правдоподобных случайных данных. У нее десятки провайдеров (имя, адрес, email, компания, дата, текст) и локализации, где значения специфичны для страны: ru_RU даст русские имена и города, en_US — американские.

Установка — одна команда:

pip install Faker

Минимальный рабочий пример. Создаем генератор с русской локалью, фиксируем зерно (Faker.seed) для воспроизводимости и запрашиваем три значения:

from faker import Faker

fake = Faker("ru_RU")
Faker.seed(42)  # фиксируем зерно, чтобы вывод повторялся

print(fake.name())
print(fake.email())
print(fake.city())

Фактический вывод (при зерне 42):

Козлова Ирина Ефимовна
visheslavzinovev@example.org
д. Ребриха

Каждый вызов метода-провайдера (name(), email(), city()) возвращает новое значение. Без Faker.seed(...) данные будут разными при каждом запуске — это нормально для наполнения тестов, но зерно удобно, когда нужно повторить один и тот же набор. Email Faker собирает по домену example.org/example.com — это зарезервированные домены для примеров, письма туда не уходят.

Так за пару строк собирается сколько угодно записей: имена пользователей, тестовые адреса, наполнение базы. Faker не проверяет данные — его задача только произвести значение нужного типа.

Pydantic: валидация и парсинг по схеме

Pydantic — библиотека валидации данных на основе аннотаций типов. Вы описываете модель как класс-наследник BaseModel с типами полей, а Pydantic при создании объекта проверяет входные данные и при необходимости приводит их к нужному типу.

Установка:

pip install pydantic

Минимальный пример. Опишем модель пользователя и передадим ей возраст строкой "25" — Pydantic сам приведет ее к int:

from pydantic import BaseModel, field_validator

class User(BaseModel):
    name: str
    age: int
    email: str

    @field_validator("age")
    @classmethod
    def age_positive(cls, v):
        if v < 0:
            raise ValueError("age must be >= 0")
        return v

u = User(name="Anna", age="25", email="anna@example.com")
print(u)
print(u.age, type(u.age).__name__)

Фактический вывод:

name='Anna' age=25 email='anna@example.com'
25 int

Строка "25" превратилась в число 25 типа int — это режим по умолчанию (гибкий), где Pydantic пытается привести данные к объявленному типу. Декоратор field_validator добавляет собственное правило поверх проверки типа.

Теперь ошибка — тройкой «неверный ввод -> фактический результат -> как исправить». Передадим в поле age строку, которую нельзя привести к числу:

from pydantic import BaseModel, ValidationError

class User(BaseModel):
    name: str
    age: int

try:
    User(name="Anna", age="двадцать")
except ValidationError as e:
    print(e)

Фактический вывод:

1 validation error for User
age
  Input should be a valid integer, unable to parse string as an integer [type=int_parsing, input_value='двадцать', input_type=str]
    For further information visit https://errors.pydantic.dev/2.13/v/int_parsing

Pydantic не «падает» с сырым TypeError, а поднимает ValidationError с адресом поля (age), типом ошибки (int_parsing) и самим неверным значением. Исправление — ловить ValidationError и обрабатывать (вернуть ошибку клиенту, залогировать, отбросить запись) либо подавать корректные данные. Именно эта предсказуемая ошибка и делает Pydantic удобным «фильтром на входе».

Связка: Faker генерирует, Pydantic проверяет

Полезная схема для тестов: Faker поставляет значения, Pydantic сразу проверяет их по модели. Если генератор случайно выдаст данные вне правил (например, возраст меньше допустимого), модель это поймает.

Полный рабочий пример — генерируем трех клиентов и валидируем каждого:

from faker import Faker
from pydantic import BaseModel, field_validator

fake = Faker("ru_RU")
Faker.seed(0)

class Customer(BaseModel):
    name: str
    age: int
    email: str

    @field_validator("age")
    @classmethod
    def adult(cls, v):
        if v < 18:
            raise ValueError("age must be >= 18")
        return v

def make_customer():
    return Customer(
        name=fake.name(),
        age=fake.random_int(min=18, max=70),
        email=fake.email(),
    )

for _ in range(3):
    c = make_customer()
    print(c.model_dump())  # модель -> словарь

Фактический вывод (при зерне 0):

{'name': 'Наина Аскольдовна Осипова', 'age': 50, 'email': 'onufri2022@example.com'}
{'name': 'Людмила Харитоновна Рожкова', 'age': 31, 'email': 'visheslav_1985@example.org'}
{'name': 'Максимова Синклитикия Юльевна', 'age': 27, 'email': 'valerjan15@example.com'}

Метод model_dump() превращает объект Pydantic в обычный словарь Python — его легко сериализовать в JSON и отправить в API или записать в файл. Так получается конвейер: fake.* создает значение, конструктор модели проверяет тип и правила, model_dump() отдает готовый словарь. Здесь random_int(min=18, max=70) гарантированно проходит валидатор; уберите нижнюю границу — и часть записей начнет падать с ValidationError, что для проверки самой границы как раз и нужно.

Выводы

  • Faker и Pydantic не конкуренты, а разные звенья: Faker создает данные, Pydantic их проверяет. Путать роли — частая ошибка новичка.
  • Faker описывается одной строкой Faker("ru_RU"), дальше вызываются методы-провайдеры; Faker.seed(n) делает вывод воспроизводимым.
  • Pydantic строится на классе-наследнике BaseModel с аннотациями типов; в режиме по умолчанию он приводит совместимые типы (строку "25" к int), а несводимые данные отвергает через ValidationError.
  • Ошибка валидации в Pydantic — не сырое исключение, а структурированный ValidationError с полем, типом ошибки и значением; ее ловят и обрабатывают.
  • В связке model_dump() отдает результат словарем, готовым к сериализации в JSON.
  • Синтаксис здесь для Pydantic 2.x; в 1.x имена другие (см. заметку в конце), учитывайте версию проекта.

Где применяется / связь с практикой

Обе библиотеки — рабочий инструмент автоматизатора тестирования и бэкенд-разработчика. Faker наполняет тестовые сценарии и базы правдоподобными данными, Pydantic проверяет тело запросов и ответов API, конфиги и данные из внешних источников. Связку удобно ставить в фикстуры тестов: сгенерировал набор, тут же проверил модель.

Освойте тему на практике

Разобрать это на практике, с фикстурами и реальными API, помогает курс Python Basic в Otus — на нем закладывается база Python, на которую опираются и тестирование, и работа с данными. Посмотреть формат и темы можно на бесплатных вебинарах до старта.

Смежные темы: Чем занимается QA-инженер, XML: что это и как с ним работать.

FAQ

Можно ли использовать Faker без Pydantic и наоборот?
Да, они независимы. Faker пригодится там, где нужны любые фейковые данные, даже без валидации. Pydantic работает с любыми входными данными — из формы, API, файла, не обязательно от Faker.

Чем отличается синтаксис Pydantic 1.x от 2.x?
В версии 2.x пользовательские валидаторы объявляют через field_validator, а модель в словарь переводит model_dump(). В 1.x это были validator и dict() соответственно. Код под 2.x на 1.x без правок не запустится.

Как Faker выдать одни и те же данные при каждом запуске?
Зафиксировать зерно генератора: Faker.seed(42) перед вызовами. При одном и том же зерне и порядке вызовов вывод повторяется — это удобно для стабильных тестов.

OTUS Журнал
Скидка 5% 14-20 сентября на курсы (popup)