Как сделать удобно расширяемый http клиент?
Самый частый паттерн при написании логгирующей http обертки в API автотестах:
Потом добавляем allure степы:
Метод разрастается, мы опять вносим изменения в класс.
Дальше захотим добавить coverage, метрики - опять изменения.
Может быть есть способ не изменяя класс?
Решение 1: Встроенные hooks в httpx
httpx уже поддерживает event hooks.
Можем передать функции, которые вызовутся до/после запроса.
Решение 2: Своя реализация
А что если захотим свой клиент?
Систему хуков можно внедрить в любой клиент - к БД или другому ресурсу.
Рассмотрим на примере httpx, как будто там нет хуков:
Создаем колбеки:
Регистрируем и используем:
Результат:
Что получается?
Мы один раз описали интерфейс для регистрации хуков, и теперь можем добавлять сколько угодно логики, не внося изменений в класс. Код становится более стабильным и расширяемым.
——————————-
📱 TG-сообщество
📱 Обучение
📱 Отзывы
Самый частый паттерн при написании логгирующей http обертки в API автотестах:
import httpx
class LogClient(httpx.Client):
def request(self, *args, **kwargs):
print(args, kwargs)
response = super().request(*args, **kwargs)
print(response.content)
return response
Потом добавляем allure степы:
class LogClient(httpx.Client):
def request(self, *args, **kwargs):
with allure.step(f"Request {args}"):
print(args, kwargs)
allure.attach(request, name="Request")
response = super().request(*args, **kwargs)
allure.attach(response, name="Response")
return response
Метод разрастается, мы опять вносим изменения в класс.
Дальше захотим добавить coverage, метрики - опять изменения.
Может быть есть способ не изменяя класс?
Решение 1: Встроенные hooks в httpx
client = httpx.Client(
event_hooks={
'request': [log_request],
'response': [log_response]
}
)
httpx уже поддерживает event hooks.
Можем передать функции, которые вызовутся до/после запроса.
Решение 2: Своя реализация
А что если захотим свой клиент?
Систему хуков можно внедрить в любой клиент - к БД или другому ресурсу.
Рассмотрим на примере httpx, как будто там нет хуков:
from typing import Callable
import httpx
from httpx import Request, Response
class Client:
def __init__(self):
self._on_request_callbacks = []
self._on_response_callbacks = []
self._client = httpx.Client()
def add_request_hook(
self, callback: Callable[[Request], None]
) -> None:
self._on_request_callbacks.append(callback)
def add_response_hook(
self, callback: Callable[[Response], None]
) -> None:
self._on_response_callbacks.append(callback)
def _run_hooks(self, value, hooks):
for hook in hooks:
try:
hook(value)
except Exception as e:
print(f"Hook error: {e}")
def request(self, method, url, **kwargs) -> Response:
request = self._client.build_request(
method=method, url=url, **kwargs
)
self._run_hooks(request, self._on_request_callbacks)
response = self._client.send(request)
self._run_hooks(response, self._on_response_callbacks)
return response
Создаем колбеки:
def log_req(request):
print(f"→ {request.method} {request.url}")
def log_resp(response):
print(f"← {response.status_code}")
def allure_req(request):
allure.attach(str(request), name="Request")
def allure_resp(response):
allure.attach(response.text, name="Response")
Регистрируем и используем:
client = Client()
client.add_request_hook(log_req)
client.add_request_hook(allure_req)
client.add_response_hook(log_resp)
client.add_response_hook(allure_resp)
client.request("GET", "https://httpbin.org/get")
Результат:
→ GET https://httpbin.org/get
← 200
Что получается?
Мы один раз описали интерфейс для регистрации хуков, и теперь можем добавлять сколько угодно логики, не внося изменений в класс. Код становится более стабильным и расширяемым.
——————————-
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥11
Как удобно тестировать брокеры сообщений?
Многие тестировщики при тестировании брокеров сообщений создают новое соединение перед каждым тестом. Если топиков в интеграционном тестировании несколько, то тесты выполняются очень долго, и каждое сообщение валидируется отдельно и последовательно в тесте.
Как можно улучшить, чтобы переиспользовать соединение и при этом проводить валидацию моментально при наступлении события? При этом делать это расширяемо и удобно.
Мы можем пойти немного в инженерию.
А что если у нас будет один Kafka listener, который будет вычитывать Kafka топики, и несколько подписчиков, которые при получении события (например, сообщения) будут выполнять свою логику?
Так мы с вами реализуем паттерн Observer.
Сначала реализуем Subject или наш KaflaListener, для простоты там будет один метод publish, который и будет уведомлять подписчиков Observer о наступлении событий.
Этот класс так же имеет метод регистрации подписчиков, которых можно сделать очень много.
Дальше опишем интерфейс наших подписчиков.
Теперь описываем конкретные подписчики, где можем сказать что делать при выполнении read_message, например валидацию или перекладывание в очередь.
Теперь мы можем увидеть, что при publish от нашего listener, наше сообщение попадет сразу во все подписчики.
Получим такой результат:
Использовать такую модель можно и в кейсе с обновлением токенов, где подписчиками будут наши клиенты, и по push-модели там будет обновляться авторизация.
Изучение данного паттерна уже включено в курс по брокерам сообщений, который выйдет после Нового года.
А пока вы можете изучить другие паттерны, такие как Proxy, Facade, Decorator, в курсе Advanced.
Многие тестировщики при тестировании брокеров сообщений создают новое соединение перед каждым тестом. Если топиков в интеграционном тестировании несколько, то тесты выполняются очень долго, и каждое сообщение валидируется отдельно и последовательно в тесте.
Как можно улучшить, чтобы переиспользовать соединение и при этом проводить валидацию моментально при наступлении события? При этом делать это расширяемо и удобно.
Мы можем пойти немного в инженерию.
А что если у нас будет один Kafka listener, который будет вычитывать Kafka топики, и несколько подписчиков, которые при получении события (например, сообщения) будут выполнять свою логику?
Так мы с вами реализуем паттерн Observer.
Сначала реализуем Subject или наш KaflaListener, для простоты там будет один метод publish, который и будет уведомлять подписчиков Observer о наступлении событий.
Этот класс так же имеет метод регистрации подписчиков, которых можно сделать очень много.
class KafkaListener:
def __init__(self):
self._clients: list[Subscriber] = []
self._is_running: bool = False
def start(self):
if self._is_running:
raise RuntimeError("already running")
self._is_running = True
def publish(self, message: str) -> None:
for client in self._clients:
client.read_message(message)
def subscribe(self, client: Subscriber) -> None:
if self._is_running:
raise RuntimeError("already running")
self._clients.append(client)
Дальше опишем интерфейс наших подписчиков.
from typing import Protocol
class Subscriber(Protocol):
def read_message(self, message: str) -> None: ...
Теперь описываем конкретные подписчики, где можем сказать что делать при выполнении read_message, например валидацию или перекладывание в очередь.
class FirstClient:
def read_message(self, message: str) -> None:
print(f"Get message from {self.__class__.__name__}, {message}")
class SecondClient:
def read_message(self, message: str) -> None:
print(f"Get message from {self.__class__.__name__}, {message}")
class ThirdClient:
def read_message(self, message: str) -> None:
print(f"Get message from {self.__class__.__name__}, {message}")
Теперь мы можем увидеть, что при publish от нашего listener, наше сообщение попадет сразу во все подписчики.
kafka = KafkaListener()
kafka.subscribe(FirstClient())
kafka.subscribe(SecondClient())
kafka.subscribe(ThirdClient())
for _ in range(10):
kafka.publish(f"message {_}")
time.sleep(2)
Получим такой результат:
Get message from FirstClient, message 0
Get message from SecondClient, message 0
Get message from ThirdClient, message 0
Get message from FirstClient, message 1
Get message from SecondClient, message 1
Get message from ThirdClient, message 1
...
Использовать такую модель можно и в кейсе с обновлением токенов, где подписчиками будут наши клиенты, и по push-модели там будет обновляться авторизация.
Изучение данного паттерна уже включено в курс по брокерам сообщений, который выйдет после Нового года.
А пока вы можете изучить другие паттерны, такие как Proxy, Facade, Decorator, в курсе Advanced.
1🔥7❤2
Хочу поделиться некоторыми слайдами из своего будущего тренинга по брокерам сообщений.
В частности, базовых проблем которые возникают при работе с Kafka в автоматизации тестирования.
А как вы тестируете и какой подход используете?
——————————-
📱 TG-сообщество
📱 Обучение
📱 Отзывы
В частности, базовых проблем которые возникают при работе с Kafka в автоматизации тестирования.
А как вы тестируете и какой подход используете?
——————————-
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
1🔥14
Привет, давненько меня не было.
Так вот, хочу рассказать о чем. Пару лет назад у меня возникла идея разработать опенсорс-фреймворк, что-то типа Django или FastAPI. То есть, что-то, что позволит быстро и удобно разработать автотесты. У меня было несколько подходов, и я даже написал такой фреймворк, который уже есть на PyPI, но не скажу, как он называется.)))
Проблема была в том, что я пытался сделать все и сразу, и было тяжело его развивать. Плюс, у меня был богатый опыт в автоматизации, но именно как разработчика опыта было мало. За последние пару лет я многому научился и разобрался. Я решил действовать более итерационно и делать инструменты так, чтобы они были полезны как тестировщикам, так и разработчикам.
Так появились инструменты restcodegen, который по Swagger-спеке генерирует Python-клиенты. Эта библиотека в отрефакторенном виде сейчас присутствует в нашей Python-платформе, и я знаю, что используется некоторыми людьми в проектах за пределами Ozon.
Вторая важная задача заключалась в удобной кодогенерации для gRPC. Подход к генерации gRPC-кода в виде плагина я подсмотрел в нашей же Python-платформе, но чтобы сделать это open source, разработал механизм для получения proto-файлов через gRPC-рефлексию. Теперь, зная хост или IP-адрес, можно легко получить Python-клиент для выбранного gRPC-сервиса.
Так появился инструмент pbreflect, и доклад про него вы можете посмотреть здесь.
Эти инструменты будут полезны любому Python-разработчику веб-приложений.
Теперь настал этап интеграции этих инструментов в сам фреймворк для разработки автотестов. Уже готова часть для работы с REST API. Сколько он экономит времени, зависит от размера вашего API, ведь по одной спецификации генерируются клиенты, тесты и фикстуры. Пользователю остается только заполнить хост своего сервиса, и дальше все, в принципе, работает. Про сам инструмент расскажу позже. Что меня удивило, так это то, что за неделю количество скачиваний составило больше 600. Пока это рекорд из всех моих библиотек. Некоторым подписчикам я уже даже дал потестить, но прошу здесь не спойлерить, об этом расскажу позже!
Так вот, хочу рассказать о чем. Пару лет назад у меня возникла идея разработать опенсорс-фреймворк, что-то типа Django или FastAPI. То есть, что-то, что позволит быстро и удобно разработать автотесты. У меня было несколько подходов, и я даже написал такой фреймворк, который уже есть на PyPI, но не скажу, как он называется.)))
Проблема была в том, что я пытался сделать все и сразу, и было тяжело его развивать. Плюс, у меня был богатый опыт в автоматизации, но именно как разработчика опыта было мало. За последние пару лет я многому научился и разобрался. Я решил действовать более итерационно и делать инструменты так, чтобы они были полезны как тестировщикам, так и разработчикам.
Так появились инструменты restcodegen, который по Swagger-спеке генерирует Python-клиенты. Эта библиотека в отрефакторенном виде сейчас присутствует в нашей Python-платформе, и я знаю, что используется некоторыми людьми в проектах за пределами Ozon.
Вторая важная задача заключалась в удобной кодогенерации для gRPC. Подход к генерации gRPC-кода в виде плагина я подсмотрел в нашей же Python-платформе, но чтобы сделать это open source, разработал механизм для получения proto-файлов через gRPC-рефлексию. Теперь, зная хост или IP-адрес, можно легко получить Python-клиент для выбранного gRPC-сервиса.
Так появился инструмент pbreflect, и доклад про него вы можете посмотреть здесь.
Эти инструменты будут полезны любому Python-разработчику веб-приложений.
Теперь настал этап интеграции этих инструментов в сам фреймворк для разработки автотестов. Уже готова часть для работы с REST API. Сколько он экономит времени, зависит от размера вашего API, ведь по одной спецификации генерируются клиенты, тесты и фикстуры. Пользователю остается только заполнить хост своего сервиса, и дальше все, в принципе, работает. Про сам инструмент расскажу позже. Что меня удивило, так это то, что за неделю количество скачиваний составило больше 600. Пока это рекорд из всех моих библиотек. Некоторым подписчикам я уже даже дал потестить, но прошу здесь не спойлерить, об этом расскажу позже!
E-CODE 2025 — IT-конференция от Ozon Tech // 13 и 14 сентября // Москва и онлайн
Reverse Engineering gRPC: генерируем gRPC-клиентов из воздуха | Доклад на E-CODE 2025
Как использовать gRPC-рефлексию для восстановления .proto-файлов без доступа к репозиторию и автоматизировать генерацию удобных Python-клиентов через собственный плагин для protoc. Демонстрация open source-библиотеки BPReflect, которая решает базовые проблемы…
🔥12👍5❤2
Привет!
Как и обещал - зарелизнул первую итерацию своего фреймворка для генерации автотестов.
Что он уже умеет?
Берёшь свою swagger/openapi спеку, одна команда и у тебя готов:
- проект с клиентами
- фикстурами
- тестами
- конфигами.
Без нейросетей, чистый, детерминированный результат.
По факту:
• создает проектную структуру
• пишет фикстуры
• пишет тесты
• пишет конфигурацию
• и всё это одной командой
Погонять можно уже сейчас, фреймворк рабочий.
А как им пользоваться - скоро запишу занятие в ступень Профешнл.
С момента релиза - почти 1000 скачиваний, практически без рекламы.
Если не заброшу (а я вроде не собираюсь) - кто знает, может когда-нибудь станет таким же популярным, как FastAPI. А чего нет?)
Следующая итерация: gRPC + Postgres.
Посмотреть пример проекта, который генерится одной командой - вот тут, достаточно только указать URL сервиса и всё взлетает🔥
Как и обещал - зарелизнул первую итерацию своего фреймворка для генерации автотестов.
Что он уже умеет?
Берёшь свою swagger/openapi спеку, одна команда и у тебя готов:
- проект с клиентами
- фикстурами
- тестами
- конфигами.
Без нейросетей, чистый, детерминированный результат.
По факту:
• создает проектную структуру
• пишет фикстуры
• пишет тесты
• пишет конфигурацию
• и всё это одной командой
Погонять можно уже сейчас, фреймворк рабочий.
А как им пользоваться - скоро запишу занятие в ступень Профешнл.
С момента релиза - почти 1000 скачиваний, практически без рекламы.
Если не заброшу (а я вроде не собираюсь) - кто знает, может когда-нибудь станет таким же популярным, как FastAPI. А чего нет?)
Следующая итерация: gRPC + Postgres.
Посмотреть пример проекта, который генерится одной командой - вот тут, достаточно только указать URL сервиса и всё взлетает
Please open Telegram to view this post
VIEW IN TELEGRAM
GitHub
GitHub - ValeriyMenshikov/e2efast: E2E Lib
E2E Lib. Contribute to ValeriyMenshikov/e2efast development by creating an account on GitHub.
🔥14👍9
Привет ребят, сегодня такой завал, хотелось подвести какие-то итоги, но наверное уже не успею)
По поводу чего спросите вы?
Сегодня у меня День Рождения)
И вы уже сделали мне подарок, наконец-то набралось 1400 человек, ну если хотите еще меня порадовать поделитесь ссылочкой на мой канал со своими коллегами.
А я и дальше смогу делиться с вами хорошим техническим контентом и классными тренингами)
Спасибо что в этот день вы со мной)
По поводу чего спросите вы?
Сегодня у меня День Рождения)
И вы уже сделали мне подарок, наконец-то набралось 1400 человек, ну если хотите еще меня порадовать поделитесь ссылочкой на мой канал со своими коллегами.
А я и дальше смогу делиться с вами хорошим техническим контентом и классными тренингами)
Спасибо что в этот день вы со мной)
1🔥37❤5
Forwarded from 📚 ProTestingInfo 🔷 Канал по тестированию 📚
2 декабря был день рождения аккаунту protestinginfo в нельзяграме!
Также присоединяйтесь.
Ровно 5 лет назад я укладывала старшего сына спать (ему было 2 месяца) и думала о работе, скучала. И сейчас скучаю, хотя скоро выхожу на частичную занятость в декрете
Так вот, я думала, что начинаю забывать основы тестирования, плюс, казалось, что дни становятся однообразными, и я загорелась желанием завести блог по тестированию.
Я начала придумывать, а как же назвать мой аккаунт, первое, что пришло в голову «ND_testing» (ND - Nadezhda Dudnik), потом начала смотреть какие ещё каналы по тестированию есть, и их оказалось много, и, по наблюдению, я придумала «ProTestingInfo»😉.
Затем я начала думать, как же нарисовать мой первый логотип.
Я изначально хотела, чтобы логотип был тёмно-синий - мой любимый цвет.
В оформлении постов мне помогает и поддерживает моя сестра Любочка, и эта картинка с днем рождения оформлена ею.
Я горела желанием собирать любую информацию, помогать себе и другим людям.
Мне нравится придумывать тесты, проводить вебинары, а сейчас есть не только курс по подготовке к собеседованиям и мини-программы, а курсы по тестированию бэкенда, тестированию gRPC API, GraphQL API, и хочется отдельно выразить благодарность Валерию Меньшикову за наше партнерство.
Занимаюсь менторской деятельностью, и более 40 менти получили оффер за 2025г, и до сих пор направляю людей, пока есть возможность.
Я также буду продолжать заниматься созданием тестов, написанием полезных постов и статей!
Делиться полезной информацией!
Спасибо за ваши отзывы.
Люблю свое дело
Желаю всем вам развития!
Благодарю за ваши реакции, комментарии и обратную связь. Ценю.
А кто недавно на моем канале, предлагаю прочитать пост про знакомство.
Будем дальше закреплять наши знания
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
51🔥9❤1👍1
Всем привет! У кого, как и у меня, работы под конец года подвалило
Я тут с подарочками)
Во-первых, я закончил записывать курс по тестированию брокеров сообщений✍️ .
Знаю, многие ждали - видео полностью готовы (самая сложная часть позади). Осталось залить на платформу и наваять лендинг.
Так же хочу напомнить про свой опенсорс restcodegen.
В последней обнове я выпилил лишние зависимости, переехал на другой парсер, так что пакет стал легче и теперь будет меньше конфликтов.
pbreflect - пофиксил баги, которые были связаны с использованием annotation.proto, и библиотека стала стабильнее.
Выпустил новый релиз e2efast - теперь фикстуры резолвятся автоматически и без багов (по крайней мере пока).
Планирую добавить, чтобы в конфиг автоматически проливался хост, а не руками заполнять.
Но для этого надо поправить парсер в restcodegen, поэтому пока всё по-старинке — хост руками.
Напомню:
• restcodegen - библиотека для генерации клиента к REST API по спецификации OpenAPI 3
• pbreflect - библиотека для получения протофайлов по URL с использованием gRPC-рефлексии и генерации клиентов
• e2efast - фреймворк для быстрого развертывания каркаса автотестов для REST-сервисов (генерация клиентов, фикстур, тестов)
В общем: пользуемся, говорим спасибо 😎 и ждём открытия продаж курса по брокерам!
——————————-
📱 TG-сообщество
📱 Обучение
📱 Отзывы
Я тут с подарочками)
Во-первых, я закончил записывать курс по тестированию брокеров сообщений
Знаю, многие ждали - видео полностью готовы (самая сложная часть позади). Осталось залить на платформу и наваять лендинг.
Так же хочу напомнить про свой опенсорс restcodegen.
В последней обнове я выпилил лишние зависимости, переехал на другой парсер, так что пакет стал легче и теперь будет меньше конфликтов.
pbreflect - пофиксил баги, которые были связаны с использованием annotation.proto, и библиотека стала стабильнее.
Выпустил новый релиз e2efast - теперь фикстуры резолвятся автоматически и без багов (по крайней мере пока).
Планирую добавить, чтобы в конфиг автоматически проливался хост, а не руками заполнять.
Но для этого надо поправить парсер в restcodegen, поэтому пока всё по-старинке — хост руками.
Напомню:
• restcodegen - библиотека для генерации клиента к REST API по спецификации OpenAPI 3
• pbreflect - библиотека для получения протофайлов по URL с использованием gRPC-рефлексии и генерации клиентов
• e2efast - фреймворк для быстрого развертывания каркаса автотестов для REST-сервисов (генерация клиентов, фикстур, тестов)
В общем: пользуемся, говорим спасибо 😎 и ждём открытия продаж курса по брокерам!
——————————-
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥19❤3👨💻1