Metadata-Version: 2.3
Name: fastapi-test-core
Version: 1.2.0
Summary: Core testing utilities: mocks, fixture factory, async helpers, API response asserts
Author: Padel Team
Requires-Python: >=3.11,<4.0
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Requires-Dist: PyHamcrest (>=2.1.0,<3.0.0)
Requires-Dist: pytest (>=7.0,<10)
Description-Content-Type: text/markdown

# fastapi-test-core

Core testing utilities for FastAPI services.

- `MockStack`, `MockConfig`, `MockSQLCursor` — lightweight mocks activated as a stack;
- `create_mock`, `create_async_mock` — one-liner `MagicMock`/`AsyncMock` factories from kwargs;
- `FixtureFactory`, `configuration_fixture` — register domain fixtures from static methods, read config from a pytest marker;
- `as_async_generator`, `as_coroutine`, `asynchronous_calling`, `DeferredAsyncTask` — async helpers;
- `assert_status_code`, `assert_api_error`, `assert_json_response` — API response checks for httpx / requests / TestClient;
- `assert_async_called_with`, `assert_not_called`, `assert_called_once`, `assert_called_times`, `assert_dict_contains`, `assert_list_contains`, `assert_exception_message` — mock-call asserts (`mock_asserts.py`, PyHamcrest);
- `slow`, `integration`, `unit`, `register_markers`, `skip_if_no_redis` — pytest markers (`markers.py`);
- `JSONResponseDict`, `JSONResponseList`, `batch` — response structures and reducers.

```bash
pip install fastapi-test-core
```

## mock_asserts

Ассерты на вызовы моков поверх PyHamcrest:

```python
from test_core import assert_called_once, assert_dict_contains

assert_called_once(mock_control.save)
assert_dict_contains(response.json(), {"status": "ok"})
```

## markers

`slow()` / `integration()` / `unit()` — тонкие обёртки над `pytest.mark`. Регистрация:

```python
# conftest.py
from test_core.markers import register_markers

def pytest_configure(config):
    register_markers(config)
```

`skip_if_no_redis()` — честная проверка: реальный TCP-коннект на `REDIS_HOST`/`REDIS_PORT`
(default `localhost:6379`) с коротким таймаутом, skip только если недоступен. Не безусловный
`pytest.mark.skip`, как было в осиротевшей test_utils.

## MockConfig

`extract(section, uppercase=True)` ведёт себя как настоящий `config_fastapi.Config.extract` —
рекурсивно приводит ключи извлечённой секции к верхнему регистру.

## Changelog

### 1.2.0
- `create_mock`/`create_async_mock` — перенесены из test_utils
- новый модуль `mock_asserts.py`: assert_async_called_with, assert_not_called, assert_called_once, assert_called_times, assert_dict_contains, assert_list_contains, assert_exception_message
- новый модуль `markers.py`: slow/integration/unit, register_markers(); skip_if_no_redis() переписан честно (реальный TCP-коннект с таймаутом), а не безусловный skip
- `MockConfig.extract(uppercase=True)` — рекурсивный uppercase ключей, как в config_fastapi
- зависимость `pyhamcrest` добавлена (требуется для mock_asserts.py)
- пин pytest `>=7.0,<10` — перенесено из неопубликованной 1.1.1
- dev-группа зависимостей (pytest, pytest-asyncio, pytest-cov); собственный набор тестов библиотеки, покрытие 100%

### 1.1.0
- MockStack, FixtureFactory, asserts, async-хелперы

