Теперь Кью работает в режиме чтения

Мы сохранили весь контент, но добавить что-то новое уже нельзя
36 лет живу, 16 лет программирую, 7 лет путешеству...  · 25 авг 2021  · ryabenko.pro

"Юнит тесты это зло" или почему я решил создать это сообщество

Пару лет назад на одном из крупных митапов для тимлидов в Москве я услышал несколько интересных высказываний о тестах:
“Юнит тесты в ограниченном количестве нужны. Но имеет смысл их писать всего наверное два.”
Более осмысленная:
“Юнит тесты удваивают или утраивают стоимость разработки”
и та самая:
“Юнит тесты - это зло”
Меня задели эти утверждения, но я понимал где скрываются корни этой проблемы.
Как юнит тесты могут убить проект
Первый раз я всерьез познакомился с юнит тестами около 10 лет назад. Компания в которой я тогда работал старалась использовать лучшие практики существовавшие на тот момент. Одной из них (вместе с Agile/Scrum/Kanban) был eXtreme Programming с техникой TDD. В лучших традициях XP тесты были возведены в абсолют и тестировать нужно было абсолютно все. Местами получалось неплохо но в какой-то момент мы стали замечать что поддержка тестов стала приносить много проблем. Даже маленькую задачу было сложно оценить потому что команда не могла предсказать сколько тестов придется чинить. Но об отказе от тестов не было и речи - тесты виделись серьезной инвестицией в стабильность системы.
Был 2010 год, мы программировали как могли. Провинциальные разработчики с большой помощью приезжих звезд лихо писали классы на тысячу строк и стоически покрывали их юнит тестами которые разрастались вдвое больше. Любое изменение кода приводило к падению десятка тестов и поддержка этих тестов занимала в разы больше времени чем написание кода. Прогон всех тестов стал доходить до часа, приходилось дорабатывать инструментарий чтобы запускать тесты в несколько потоков и по частям.
Тесты заставляли нас страдать физически. Для борьбы с тестами часть команды отправили на тренинг в столицу и оказалось что все что мы считали юнит тестами таковым не является. Начался серьезный рефакторинг, самые вопиющие классы и тестами пустили под нож, критические части системы переписали с нуля. Мы сделали колоссальную работу над ошибками и подняли уровень команды. А потом у стартапа закончились деньги.
Хватило бы времени если бы мы не тратили океан времени на поддержку тестов и доработку инструментария, а вложили это время и силы в разработку? Сложно ответить, вопрос с подвохом. Но однозначно тесты были одним из гвоздей которые мы - разработчики - методично забивали в крышку стартапа.
Виноваты ли тесты? Тесты сами по себе очень полезный и эффективный инструмент, но используя его неправильно легко получить результат противоположный ожидаемому.
Воз и ныне там
В 2012 году я сделал доклад по юнит тестами на DevConf
В том же году пообщался с командой из Санкт Петербурга и обсудили их проблемы с тестированием. За последние 2 года я поговорил о тестах с оффлайн командами из Москвы и распределенными командами с разработчиками со всего мира: за 8 лет вопросы не изменились
Разработчики готовы писать тесты, но требуют на них больше времени. Бизнес готов инвестировать в стабильность системы, но хочет уменьшать time to market а не увеличить его. Часто обсуждение заходит в тупик - внедрение тестов вскрывает проблемы к решению которых команды не готовы. Но и отказываться от тестов никто не спешит.
Информации по тестам в интернете очень много, но большинство авторов не утруждает себя описанием фундамента юнит тестирования и TDD, переходя к написанию тестов на калькулятор.
Я хочу исправить это и помочь построить базу на которую можно опираться используя в работе такой сложный и полезный инструмент как юнит тесты.
Программирование+1
2 эксперта согласны
Василий Горчаков
подтверждает
Принципиально нужное и полезное явление превращено в собственную противоположность. Тут как в казино - нужно уметь... Читать дальше
@Василий Горчаков, TDD это методология, казино это азарт :)
Методология гарантирует повторяемость результата при правильном использовании. Но вопрос границ и крайностей в сфере программирования очень важный.

"Но имеет смысл их писать всего наверное два." это не опечатка? Перечитал несколько раз это предложение, но так его и не понял.

@Виталий Сергеев, это цитата. Смысл посыла был в том, что (по мнению докладчика) на любой код достаточно написать всего два теста: проверяющий положительный сценарий и проверяющий наличие ошибки при негативном сценарии.

Я почитал посты ниже ну и я слушал твой мастер класс по TDD и у меня сложилось впечатление, что правильные юнит тесты, это такие тесты которые тестируют интерфейсы класса.
Проверяют что классы выдают то что обещает интерфейс.
Ну и если код написан выполняя S и O из принципов SOLID, то и не должно изменение кода где то вызывать падение каких то других тестов.
S. Класс отвечает за что то одно, это что то одно и тестуруют достаточно простые тесты..
O. Интерфейсы же уже сделанные, которые тестируют тесты не должны изменятся, должны только расширятся, старые тесты при этом не должны ломаться.
Но судя по описанию проблем - вызывает.
Почему?
@Михаил Чудинов, не совсем верно.
Проверяют что классы выдают то что обещает интерфейс.
Тесты проверяют поведение кода, в то время как интерфейс только объявляет методы. У классов реализующих один и тот же интерфейс поведение может отличаться весьма существенно, но снаружи это не будет заметно.
Например мы хотим рассылать электронные письма, можем создать интерфейс `MailerInterface` с методом `send($message)` (где `$message` включает тему, текст, кому, от кого и т.д.). Для системы не важно как именно сообщение будет отправлено, главное чтобы сервис отправки реализовывал данный интерфейс.
Затем мы можем написать две реализации: отправка встроенной функцией и отправку через mailgun. Для каждой реализации нужно написать отдельный тест, проверяющий поведение самой реализации (вызов функции mail в первом случае и HTTP запрос к API mailgun во втором), а соответствие интерфейсу проверяется самим интерпретатором, поэтому в тесте мы его не тестируем.
Таким образом мы добиваемся SRP (каждая реализация имеет одну ответственность), OCP - мы можем расширять систему добавляя новые реализации интерфейса и внедрять конкретные реализации интерфейса при бутстрапе системы. И так мы можем избежать проблем с поддержкой системы в дальнейшем.
Это по поводу описания сообщества.
Как писать в 2 раза больше кода за половину времени?
Лучше меньше, да лучше. (Ленин)
Я бы почитал, как писать в 2 раза меньше кода за такое же время =)
@Тимур Алтынов, тут стоит прояснить. Лозунг скопирован у Скрама - "The Art of Doing Twice the Work in Half the Time", и он не подразумевает раздувание работы в два раза.
У любой программы есть 2 составляющие - продуктовая и техническая. Продуктовая составляющая отвечает за то, какой объем работы должен быть выполнен и по возможности уменьшить объем работы программиста. После того как определились с тем что нужно сделать... это просто нужно сделать и написать какой-то объем кода. Тема группы не про то, чтобы писать в два раза больше, чем изначально было нужно, а в том, чтобы написать нужный объем кода в 4 раза быстрее :)