Skip to main content

mockable for ses

Project description

mockable

Библиотека для управления моками через конфигурацию без изменения бизнес-логики приложения.

Содержание


Установка и настройка

Установка

pip install mockable

Пример использования

from dataclasses import dataclass
from typing import Any, Dict

# 🔴 0. pip install mockable
# 🔴 1. Импортируем
from mockable import (
    MethodMockConfig,
    MockConfig,
    MockFixture,
    TestCaseType,
    mockable,
    mockable_class,
    set_mock_config,
)

# 🔴 2. Создаем переменную конфига
start_config = None


# 🔴 3. Пишем функцию инициализации конфига
# Это нужно, чтобы не инициализировать конфиг
#   при продовых запусках и не засорять память
def init_custom_config():
    global start_config
    # Конфиг моков
    start_config = MockConfig(
        # Какие кейсы включить, при тестировании
        # ⚠️ Если в здесь будет неправильно прописано имя метода, то мок не сработает
        active_cases={
            "api_method_a": TestCaseType.NEGATIVE,
            "api_method_b": TestCaseType.NEGATIVE,
            "outside_method_a": TestCaseType.POSITIVE,
        },
        # Описание кейсов
        # Структура ->
        #   <название метода>: MethodMockConfig(
        #       <характер случая>: MockFixture(
        #           result|side_effect|exception|file_path,
        #           description (опционально)
        #       )
        #   )
        methods={
            "api_method_a": MethodMockConfig(
                positive=MockFixture(
                    result="MOCK POSITIVE api_method_a",
                    description="описание позитивного кейса (штатная ситуация)",
                ),
                negative=MockFixture(
                    result="MOCK NEGATIVE api_method_a",
                    description="описание негативного кейса (например не хватило слотов)",
                ),
                special=MockFixture(
                    result="MOCK SPECIAL api_method_a",
                    description="особый случай (всего один слот, особенный врач)",
                ),
                error=MockFixture(exception=ValueError("User not found")),
            ),
            "api_method_b": MethodMockConfig(
                positive=MockFixture(
                    file_path="api_method_b_positive.json",
                    description="Путь к .json файлу с моком",
                ),
                negative=MockFixture(result="MOCK NEGATIVE api_method_b"),
            ),
            # ⚠️ Пример работы с функциональными моками
            "outside_method_a": MethodMockConfig(
                positive=MockFixture(
                    side_effect=lambda a: f"MOCK POSITIVE OUTSIDE A {a}",
                    description="Особая функциональность в моках",
                ),
                special=MockFixture(
                    side_effect=lambda a: f"MOCK SPECIAL OUTSIDE A {a}",
                ),
            ),
        },
    )

    # 🔴 3.1 Устанавливаем конфиг
    set_mock_config(start_config)


@dataclass
class Config:
    is_mock: bool = True


@mockable
def outside_method_a(a) -> str:
    return f"REAL {a}"


# 🔴 4. Добавляем @mockable_class
@mockable_class
class MedicineAPI:
    def __init__(self):
        self.cfg = Config()

        # 🔴 5. Пишем условие для is_mock
        if self.cfg.is_mock:
            init_custom_config()

    def api_method_a(self) -> str:
        # C включенным моком код ниже не запустится
        return "REAL"

    def api_method_b(self) -> Dict[str, Any]:
        # C включенным моком код ниже не запустится
        return {"result": "REAL"}


def main():
    api = MedicineAPI()
    print("Результат api_method_a ->", repr(api.api_method_a()))
    print("Результат api_method_b ->", repr(api.api_method_b()))
    print("Результат outside_method_a ->", repr(outside_method_a("some data")))


main()

Поддерживаемые сценарии

Сценарий Назначение
POSITIVE Штатное успешное выполнение
NEGATIVE Ожидаемый негативный бизнес-сценарий
SPECIAL Особый или граничный случай
ERROR Генерация исключения

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

MockConfig

Основной объект конфигурации библиотеки.

Содержит список активных сценариев и описание доступных моков.

Поля

Поле Тип Описание
active_cases dict[str, TestCaseType] Активный сценарий для каждого метода
methods dict[str, MethodMockConfig] Описание доступных моков

Пример

start_config = MockConfig(
    active_cases={
        "method_a": TestCaseType.POSITIVE,
        "method_b": TestCaseType.NEGATIVE,
        "method_c": TestCaseType.SPECIAL,
        "method_d": TestCaseType.ERROR,
    },
    methods={
        "method_a": MethodMockConfig(...),
        "method_b": MethodMockConfig(...),
        "method_c": MethodMockConfig(...),
        "method_d": MethodMockConfig(...),
    }
)

⚠️ Имя метода в active_cases должно точно совпадать с именем метода в methods, иначе мок не будет применён.


MethodMockConfig

Описывает набор сценариев для одного метода.

Поле positive является обязательным. Остальные сценарии опциональны.

Поля

Поле Обязательное Описание
positive Да Штатное выполнение
negative Нет Негативный сценарий
special Нет Особый или граничный случай
error Нет Исключение

Пример

MethodMockConfig(
    positive=MockFixture(...), # Обязательное!
    negative=MockFixture(...), # Опционально
    special=MockFixture(...),  # Опционально
    error=MockFixture(...),    # Опционально
)

MockFixture

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

Для результата использовать следующие параметры:

Поле Описание Приоритет
result Возвращает заранее подготовленное значение 4
file_path Загружает результат из JSON-файла 3
side_effect Выполняет пользовательскую функцию 2
exception Вызывает исключение 1

Дополнительно можно указать:

Поле Описание
description Описание назначения сценария

Пример

MethodMockConfig(
    positive=MockFixture(
        result={"status": "success"},
        description="Штатное выполнение",
    ),
    negative=MockFixture(
        result={"status": "error"},
        description="Недостаточно данных",
    ),
    special=MockFixture(
        result={"status": "special"},
        description="Особый сценарий",
    ),
    error=MockFixture(
        exception=TimeoutError("Service unavailable"),
        description="Сервис недоступен",
    ),
)

Пример использования side_effect

Через lambda:

MockFixture(
    side_effect=lambda value: f"Result = {value}"
)

Через отдельную функцию:

def mock_user_response(user_id: int) -> dict:
    return {
        "user_id": user_id,
        "name": "Mock User",
        "status": "active",
    }


MockFixture(
    side_effect=mock_user_response
)

Пример использования file_path

MockFixture(
    file_path="mocks/method_a/positive.json"
)

Рекомендации по MockFixture

  1. Заполняйте поле description.
  2. Для сценария ERROR используйте exception.
  3. Крупные ответы рекомендуется хранить в JSON-файлах.
  4. Использовать абсолютные пути к JSON-файлам.
  5. Использовать единый стиль именования файлов.

Примеры:

/opt/mocks/method_a_positive.json
/opt/mocks/method_a_negative.json

или

/opt/mocks/method_a/positive.json
/opt/mocks/method_a/negative.json

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

mockable-0.0.2.tar.gz (6.7 kB view details)

Uploaded Source

Built Distribution

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

mockable-0.0.2-py3-none-any.whl (7.1 kB view details)

Uploaded Python 3

File details

Details for the file mockable-0.0.2.tar.gz.

File metadata

  • Download URL: mockable-0.0.2.tar.gz
  • Upload date:
  • Size: 6.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.9

File hashes

Hashes for mockable-0.0.2.tar.gz
Algorithm Hash digest
SHA256 82fffed84d7fb178826ad5add433f8440ae9655684a84ac7e5110196d0c73866
MD5 ffbacac1f58bb4aad247c9c30944758f
BLAKE2b-256 1c9cac00cf648a61e7867d136b29514b5cf33fe2ac9a990d623ee3ac2f3bae96

See more details on using hashes here.

File details

Details for the file mockable-0.0.2-py3-none-any.whl.

File metadata

  • Download URL: mockable-0.0.2-py3-none-any.whl
  • Upload date:
  • Size: 7.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.9

File hashes

Hashes for mockable-0.0.2-py3-none-any.whl
Algorithm Hash digest
SHA256 01bb09f7a47793913a087f38d41cd77bd22efb37ad5b1a725177d404e392119e
MD5 d9c12608eb3f9b35ed75ae5c6bfc377b
BLAKE2b-256 906154f4a66435496dada0a7deca42bb84a306f483c10356431669463e9e2f25

See more details on using hashes here.

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