Skip to main content

Pydantic-factry тестовых данных для генерация payload-ов

Project description

payforge

payforge – небольшая библиотека для QA-автотестов, которая помогает собирать тестовые payload-ы на базе Pydantic-моделей.

Идея простая: одна модель описывает структуру запроса. По ней можно собрать payload для API, точечно переопределить нужные поля, сломать данные для негативного теста и этой же моделью проверить ответ.

Установка

pip install payforge

Из обязательных зависимостей – только pydantic>=2.

Генераторы случайных данных, например Faker, библиотека не подтягивает. Их можно подключить отдельно, если они нужны в проекте.

Быстрый старт

from payforge import DataFactory, FactoryModel
from pydantic import Field


class Config(FactoryModel):
    token: str = "default-token"
    timeout: int = 30


class Webhook(FactoryModel):
    list_id: str = Field("L-1", alias="list")   # API ждёт ключ "list"
    config: Config = Field(default_factory=Config)


class WebhookFactory(DataFactory):
    pass


f = WebhookFactory()

# Собрать валидный payload:
f.build(Webhook)
# {"list": "L-1", "config": {"token": "default-token", "timeout": 30}}

# Переопределить вложенное поле:
f.build(Webhook, **{"config.token": "secret"})
# {"list": "L-1", "config": {"token": "secret", "timeout": 30}}

# Собрать payload для негативного теста:
f.build_invalid(Webhook, field="config.timeout", value="not-a-number")

# Собрать несколько payload-ов:
f.build_many(Webhook, count=3, each=lambda i: {"config.token": f"tok-{i}"})
# [{...tok-0...}, {...tok-1...}, {...tok-2...}]

# Получить типизированный экземпляр модели:
wh = f.build_model(Webhook)

# Проверить ответ API той же моделью:
f.validate(Webhook, api_response)
# -> Webhook | SchemaValidationError

Случайные значения

payforge специально не зависит от Faker или других генераторов данных. Так библиотека остаётся лёгкой, а проект сам решает, чем генерировать тестовые значения.

Например, Faker можно подключить через default_factory:

from faker import Faker
from pydantic import Field

fake = Faker()


class User(FactoryModel):
    name: str = Field(default_factory=fake.name)
    email: str = Field(default_factory=fake.email)

Как пользоваться

Модель можно передать классом или строкой

Все основные методы принимают entity:

  • класс Pydantic-модели, например Webhook;
  • строковый ключ из entities, если хочется вызывать фабрику по имени.

Рекомендуемый вариант – передавать сам класс модели. Так не нужен реестр, а IDE лучше понимает типы, особенно при использовании build_model().

f.build(Webhook)

Если удобнее обращаться к моделям по строковым ключам, можно объявить entities:

class WebhookFactory(DataFactory):
    entities = {
        "webhook": Webhook,
    }


WebhookFactory().build("webhook")

Если строковый ключ неизвестен или реестр не объявлен, будет выброшена ошибка UnknownEntityError.

Валидация и негативные тесты

По умолчанию build() собирает payload и прогоняет его через модель.

f.build(Webhook)

Это поведение соответствует validate=True.

Если в overrides передать значение неподходящего типа, Pydantic выбросит ValidationError.

f.build(Webhook, **{"config.timeout": "not-a-number"})
# pydantic.ValidationError

Для негативных тестов можно отключить повторную валидацию:

f.build(
    Webhook,
    validate=False,
    **{"config.timeout": "not-a-number"},
)

В этом режиме фабрика сначала собирает валидную базу из дефолтов модели, а потом аккуратно накладывает переопределения поверх неё. Соседние поля при этом не теряются.

Важно: для validate=False модель должна уметь создаваться без аргументов. То есть у всех обязательных полей должны быть значения по умолчанию или default_factory.

build_invalid

build_invalid() – короткий способ собрать payload для негативного теста.

f.build_invalid(
    Webhook,
    field="config.timeout",
    value="not-a-number",
)

Под капотом это валидная база плюс одно испорченное поле. Значение из field накладывается последним, поэтому оно перебивает остальные overrides, если есть конфликт.

Несколько payload-ов

Метод build_many() собирает список payload-ов.

f.build_many(Webhook, count=10)

Общие значения можно передать как обычные overrides – они применятся ко всем элементам:

f.build_many(Webhook, count=3, list_id="SHARED")

Если каждому элементу нужны свои значения, используйте each:

f.build_many(
    Webhook,
    count=3,
    each=lambda i: {"config.token": f"tok-{i}"},
)

Можно сочетать общий override и индивидуальные значения:

f.build_many(
    Webhook,
    count=2,
    list_id="SHARED",
    each=lambda i: {"list": f"L{i}"},
)

Если одно и то же поле задано и в общих overrides, и в each, победит значение из each.

Особенности:

  • count=0 вернёт пустой список;
  • отрицательный count выбросит ValueError;
  • параметры validate, exclude_none и by_alias пробрасываются в build().

Вложенные поля и alias-ы

Поля можно переопределять по имени поля модели или по alias-у.

Для вложенных моделей используется dotted-path:

f.build(Webhook, **{"config.token": "x"})

Так меняется только config.token, а остальные поля внутри config остаются на месте.

Сериализация по умолчанию идёт с by_alias=True, поэтому поле:

list_id: str = Field("L-1", alias="list")

попадёт в payload как:

{"list": "L-1"}

Это же учитывается и в негативных сценариях. Если переопределить поле по имени list_id, в итоговом payload всё равно будет ключ list, а не два разных ключа list и list_id.

Валидация ответа API

Ответ API можно проверить той же моделью:

result = f.validate(Webhook, api_response)

Если ответ подходит под схему, метод вернёт экземпляр модели.

Если данные не прошли валидацию, будет выброшена SchemaValidationError. В поле .errors лежит структурированный список ошибок Pydantic.

Ошибки

payforge использует свои ошибки там, где нужно отделить ошибки фабрики от обычных ошибок Pydantic.

UnknownEntityError

Возникает, если в фабрику передали строковый ключ, которого нет в entities, или если реестр entities не объявлен.

f.build("unknown")

SchemaValidationError

Возникает при проверке ответа API через validate(), если ответ не соответствует модели.

try:
    f.validate(Webhook, api_response)
except SchemaValidationError as e:
    print(e.errors)

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

payforge-0.1.0.tar.gz (10.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

payforge-0.1.0-py3-none-any.whl (10.3 kB view details)

Uploaded Python 3

File details

Details for the file payforge-0.1.0.tar.gz.

File metadata

  • Download URL: payforge-0.1.0.tar.gz
  • Upload date:
  • Size: 10.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for payforge-0.1.0.tar.gz
Algorithm Hash digest
SHA256 2156338e2dd4b2d7226528f1339bcf53b13ac6a3bda445c2a5988ae16ce5da54
MD5 835c1045628b49f449fc6c93a6de46a8
BLAKE2b-256 e2e3dd495278e71533248ea0dabd655b9a8d03b335a1e5f55b1fc9ceeb856d30

See more details on using hashes here.

Provenance

The following attestation bundles were made for payforge-0.1.0.tar.gz:

Publisher: publish.yml on TheGreatPepix/payforge

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file payforge-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: payforge-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 10.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for payforge-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 82abe4cd1dc815df7bcf17188f492e54dbb410e6de63d930f8d7c3e5f8529d5c
MD5 3507a2f0f5ea2259a9156cb1df01c3bb
BLAKE2b-256 8e64a4606db0716aad8f26b3b777a5ea81830bf087a5d90192d941cf3e094abb

See more details on using hashes here.

Provenance

The following attestation bundles were made for payforge-0.1.0-py3-none-any.whl:

Publisher: publish.yml on TheGreatPepix/payforge

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page