TGViewer
FastNews | Никита Пастухов FastNews | Никита Пастухов @fastnewsdev · 2.59K subscribers
Post #305 1.34K
FastNews | Никита Пастухов По многочисленным заявкам немногочисленного Андрея попытаюсь изложить практические аспекты идологии TDD Коротенько не получилось, поэтому вот ссылка на фул. Краткие тезисы для ЛЛ: 1) Цикл TDD: красный тест – зеленый тест – рефакторинг, повторяем 2) Держим…
TDD в большом существующем проекте

На этом канале уважают #TDD, и я про него уже писал. Но это все были теоретические выкладки, и меня постоянно спрашивали - "приведи пример из практики", или "а как внедрять TDD в существующий проект?".

Чтож, сейчас в FastStream ведется работа над большой фичей (PR-2867) - поддержкой многоброкерности. И вот, одним из аспектов этой фичи является поддержка тестирования кросс-брокерных взаимодействий. Фича большая, сложная, поэтому она идеально иллюстрирует TDD-flow.

Итак, наша проблема: есть 2 брокера, которые публикуют сообщения друг другу.


broker1 = RabbitBroker()
broker2 = RabbitBroker()

@broker1.subscriber("queue-1")
# broker2 публикует сообщения в queue-2 (broker1)
@broker2.publisher("queue-2")
async def handler1(msg): ...

@broker1.subscriber("queue-2")
async def handler2(msg): ...


Проблема в том, что текущая реализация TestBroker не поддерживает кросс-брокерные взаимодействия - т.е. TestBroker(broker2) не знает про подписчиков broker1, и выкидывает SubscriberNotFound ошибку (хотя в реальности очередь слушается другим брокером).

К слову, эту проблему я отловил, когда писал тесты на многоброкерность

Итак, решение, которое мы хотим видеть - тестовый брокер должен знать обо всех подписчиках всех брокеров одного типа. Что-то типа такого:


# TestRabbitBroker должен знать обо всем
async with TestRabbitBroker(broker1, broker2) as (br1, br2):
...


Это очень большое и сложное изменение, которое будет гораздо проще разбить на шаги. Каждый шаг будем проверять на существующих тестах (они не должны падать) - это наши чекпоинты. А в конце - новый тест должен проходить.

Итак, наши шаги:

1️⃣ Внутри TestBroker меняю self.broker на self.brokers: list[...]:


class TestBroker:
def __init__(self, broker):
self.brokers = [broker] # было: self.broker = broker


Публичный API тот же, поведение то же - но внутри уже множественность. Запускаем существующие тесты - они должны проходить. Коммитим.

2️⃣ Учу TestRabbitBroker(broker1, broker2) оборачивать оба брокера независимо - пока что эквивалент двух раздельных TestRabbitBroker(broker1) as br1, TestRabbitBroker(broker2) as br2. Никакого шеринга подписчиков, просто чтобы новый синтаксис заработал и as (br1, br2) корректно распаковывался.


class TestBroker:
def __init__(self, *brokers):
self.brokers = list(brokers)


Тесты не поломались, значит все хорошо. Коммитим.

3️⃣ Теперь TestRabbitBroker(broker1, broker2) действительно учитывает подписчиков всех включённых брокеров - broker2.publish доезжает до подписчиков broker1. И теперь наш новый тест должен проходить:


async with TestRabbitBroker(broker1, broker2) as (br1, br2):
await br1.publish("hello", "queue-1")
handler2.mock.assert_called_once_with("processed: hello") # ✅


- наконец зелёный.

А потом уже Claude натянет изменения на другие брокеры по аналогии

Что важно: на каждом из шагов все существующие тесты продолжали проходить. Я ни разу не сидел в состоянии "я переписал половину ядра, все красное, но еще чуть-чуть - и все заработает". Каждый коммит - самостоятельный, откатываемый, не разносит чужие пайплайны. А если бы я не сквошил, это еще и ревьюить было бы просто😂

Так вот - формула, ради которой это все затевалось:

Если ты упёрся в "слишком большое изменение, чтобы сделать за раз" - это значит "пора резать на шаги, между которыми тесты проходят".


В эпоху, когда LLM пишут код тоннами, ценность тестов не падает, а только растёт. Тесты - это контракт поведения. Без них ни ты, ни нейронка не знаете, что значит "работает". Поэтому я и топлю за TDD. Пусть лучше нейронка пишет реализацию по моим тестам - меня не сильно волнует, что внутри, если все мои контракты на ожидаемое поведение выполняются.

#программирование #TDD
GitHub feat: add multibrokers support by Lancetnik · Pull Request #2867 · ag2ai/faststream Adds multibroker support across the application stack (internal application, FastStream app, ASGI integration) and updates related tests. from faststream import FastStream, Logger from faststream.n...
  • 👍 11
  • ❤ 4
  • 🔥 2
  • 👏 1
More from @fastnewsdev
  1. Sep 22, 2026Еще недавно я вайнил, что нейронки нельзя использовать в OpenSource, т.к. они не вывозят т…
  2. Sep 20, 2026Последние 2 недели я заметил, что Opus 5 значительно отупел в Claude Code. Обычно такое сл…
  3. Sep 18, 2026С днем рождения🎉 Сегодня, ровно 3 года назад, 18 сентября 2023 года, вышла первая версия…
  4. Sep 17, 2026Забавно, что лучшую иллюстрацию OpenSource комьюнити я нашел в сериале про рестораны... См…
  5. Sep 14, 2026Я снова пропустил #digest агенсткого тулинга, потому что там все как-то тухленько. Но кое-…
  6. Sep 10, 2026Я сам себя заменю. Это мой карьерный план! У Прокопова был интересный пост: 20 лет точил с…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →