Pull to refresh

Comments 24

Не знаю зачем заминусили: норм tdd вводная, не лучше и не хуже многих о premature testing на хабре.

Автор: @xini в описании тестов sociable задвоилось. Все же Sociable и Solitary Unit Tests. В английской версии статьи та же ошибка, но ссылка на английскую версию тоже с ошибкой, ведёт на 404.

А по теме - tdd прекрасно работает с ai агентами. Известно, что модели с самого начала писали тесты лучше, чем сам код. Потому даём тз, просим написать тесты, если хреновые тесты - уточняем тз. Тесты устраивают - просим написать код проходящий тесты . В этой цепочке модель пишет код явно лучше, чем в случае код по тз напрямую.

Спасибо за замеченную опечатку, поправил.
Согласен насчет использования ИИ. Хотя я могу доверить написать код по тестам, но все таки тесты еще пишу сам. Процесс написания тестов позволяет сфокусироваться и определить конечный результат, который я хочу видеть

Сейчас бы в 2025 писать тесты ради тестов. Эта статья на 100% передает весь дух TDD (даже половины не осилил).

Софт становится легаси еще на этапе планирования. Сейчас кто первый выкатил киллерфичу того и тапки. Эра предрелизов и постфиксов. Все остальное шелуха.

И это огорчает. Общество довольно непривередливо, что, как мне кажется, довольно несправедливо.
Касательно ТДД, ИМХО, тесты выступают в качестве спецификации. Но я работаю - ТЗ часто переписывают, добавляют и изменяют старый функционал, так как, "Уточнили - не так работает/не понравилось/подставить свое". В таком случае все переписывать, конечно, самоубийственно. В теории, практика оч крутая, на практике хз, может кому-то подойдет

Я работаю через ТДД и там где есть возможность пытаюсь рефлексировать стоит ли оно того.

Пока набралось два кейса:

  1. Сравнение трудозатрат на первоначальную разработку и её полный реинжиниринг

  2. Субъективное ощущение продакта на разработку большой фичи (человеко-год) по ТДД в сравнении с другими фичами в том же проекте. Тут ретру пока не публиковал

И в обоих кейсах разработка по ТДД была не медленнее разработки без тестов и команда допуска в 2-4 раза меньше багов.

Ну то есть с ТДД можно шипать фичи с той же скоростью, но при этом спокойно спать и в целом меньше стрессовать:)

На сегодня тесты внезапно приобретают совершенно новый смысл: агент пишет тебе код новой фитчи, согласно описанию, потом он же пишет на него тесты, опять по твоим требованиям. Потом он же отлаживает код, чтобы тесты перестали падать. Потом он же спотыкается о падающие тесты когда пишет новый код для следующей фитчи.

В итоге тесты нужны агенту, чтобы абы как накиданный им сырой код ожил.

Я не уверен что это уже стабильная практика. Иногда удается такое провернуть, иногда одни мучения. Напишите если у вас это пошло.

У меня такое работает. Но есть нюанс. Код пишу я сам, а тесты пишет гопота. А потом, когда это с треском падает, я иду разбираться, что же не работает - тесты или код. А падает оно примерно всегда.

Не раскрыто из-за чего падает :)

80% - лажа гопоты, 20% - моя лажа. Ну примерно так. В расчёте на строчку кода гопота лажает намного чаще, тесты находят у меня так много ошибок просто потому, что я знаю, что именно надо тестировать.

Вместо описания новой фичи, я пишу тест агенту. Агент пишет код, я пишу следующий тест и так далее, пока не получится код новой фичи.

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

Когда пишешь сначала код, то работают определенные приемы декомпозиции задачи. Обычно или это декомпозиция от функций, когда от более общих задач спускаемся к частным и/или формируется определенная архитектура классов, на которой последовательно реализуем юз-кейзы. Если начинать от тестов, то это совсем другой навык. У меня лично сразу взрывается мозг от непонимания как все будет работать, без привычного пути декомпозиции. Т.е. если я начинаю думать как должна работать система в конкретном второстепенном тестовом случае я не могу еще понять как все будет работать в целом и получаю слишком много вариантов.

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

Спасибо, хорошая и нужная статья.

Только я бы добавил про

Изолируйте все внешние зависимости

Ваша предметная область, ваша бизнес-логика, ваш основной модуль, причина, по которой вы пишете программное обеспечение, его самое сердце — должны быть защищены от внешнего мира.

У меня последние лет 5 в куче разных проектов (среди прочих - автоматизация выделенного бизнес-процесса крупного ритейлера, медтех, автоматизация работы юридического департамента) 90% "причины по которой я пишу ПО" - положить данные в РСУБД. И поэтому 90% кода тестировать в изоляции от внешнего мира особого смысла нет. В общем, на мой взгляд, изоляция внешних зависимостей - не универсальное правило и нужна только в сложных предметных областях (я таких не видел, но предполагаю, что к ним относится банкинг, страхование, логистика, e-commerce).

А в остальных случаях эффективнее по соотношению трудозатраты/(скорость + качество разработки), писать тесты как минимум с реальным PostgreSQL на RAM-диске.

И если заморочиться, такие тесты будут не критично медленнее - до 10 секунд на запуск 1 теста, и по 50мс в среднем на тест при запуске всего набора.

В остальном - всё плюсую.

Мир не черно-белый, как я говорил в конце статьи, не существуют универсальных подходов. В моей практике, каждый раз, когда я говорил себе "Не стоит тут тратить время на абстракции, можно напрямую работать с конкретными технологиями (зависимостями)", на следующий день появлялась необходимость либо как-то сложно проверять corner case либо поддерживать несколько похожих технологий. Тогда пригодились бы правильные абстракции, и приходилось все равно их внедреть позже чем следовало бы

Когда я начинаю писать функционал, я понятия не имею, как он будет выглядеть. И понятия не имею, как его тестировать. За время разработки функционала его архитектура может поменяться десять раз. Если начинать с тестов, то в каждой итерации надо будет и тесты переделывать. А в конце всё равно окажется, что тестируют они не то и не так.

Я для себя нашёл тот этап, когда наиболее разумно писать тесты. Это когда сложный функционал готов, работает, но ещё не отлажен. Вот тогда можно и подумать, а что и как лучше протестировать. Но это уже ни разу не TDD.

Это, наверное, зависит от контекста.

Я обычно перед тем как писать какой-то код, проектирую и согласовываю АПИ с фронтом. И тесты пишу через это АПИ. А если там будут существенные изменения, то модификация тестов - будет меньшей из проблем:)

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

Чсто встречаю такое утверждение. Мне кажется, мне кажется оно в большей степени касается конкретных реализаций. Сложно представить ситуацию, когда вы уже готовитесь писать решение, но не знаете какая у вас бизнес проблема. На примерах из статьи:
Беря задачу в работу я точно знаю, что бизнесу необходимо показывать оценку книги из стороннего сервиса. Исходя из этого я пишу тест вида

bookService.createBook(bookId, ...);
fakeRatings.createRating(bookId, 5);
assertThat(bookService.rating(bookId)).isEqualTo(5);

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

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

Как только выяснится, что для вычисления рейтинга необходимо передать ещё один какой-нибудь параметр/зависимость, а выяснится это на этапе реализации алгоритма вычисления рейтинга, придётся бежать по всем тестам и править вызовы

Пример из опыта приведу, написали тесты для бизнес логики (исходя из бизнес требований), на этапе реализации выяснилось, что нужно прокинуть ещё параметр TaskId (технический параметр, неинтересный бизнесу, собственно, поэтому в тестах его не было). Начали копать и выяснили, что параметр этот в общем то нужен, чтоб пихать его в каждую запись лога, просто предыдущие разработчики не знали про структурный лог и mdc (дело на джаве было).

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

Проблема как раз известна. Мне нужно дать решение. Каким оно будет - я пока не знаю. Мне нужно сделать ресёрч. Нужно накидать прототип, проверить, как он решает проблему. Потом переписать, потому что пришла в голову идея получше. Оно сразу не получается найти это решение.

Я не спорю, есть задачи (как правило сильно мельче и сильно детерминированнее), которые можно и нужно делать через TDD. Но у меня вот так. Когда я решаю проблемы конкретных людей, а не железяк, мне нужно показывать прототип конкретным людям и получать фидбек. Мне никакие тесты не скажут, решил я проблему или нет.

Если вы не знаете что тестировать значит либо не поняли задачу, либо вам её плохо поставили, стоит остановиться и подумать над задачей лучше, если задача звучала как сделай как-нибудь, то и делай как нибудь, получишь соответственно, TDD занимается вопросами как надо писать код, как не надо изучает психиатрия

Если вы не знаете что тестировать значит либо не поняли задачу, либо вам её плохо поставили

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

Поэтому у вас сейчас всё просто. Не надо абсолютизма. TDD - не волшебная пилюля, у него есть границы применимости. Если вы не видите их - значит вы просто слепо верите в TDD.

TDD занимается вопросами как надо писать код, как не надо изучает психиатрия

Нет

Согласен, TDD - не волшебная пилюля. Такой подход не слишком подходит, если мы не знаем в какую сторону идти. Как вы упомянули, могут потребоваться PoC и прочие исследования чтобы определить, где мы хотим оказаться в будущем. После этого в дело вступает TDD, которое как каток помогает прокладывать дорогу к пункту назначения

Sign up to leave a comment.

Articles