Заметки Романа Теличкина

Интеграционные или модульные тесты?

Май 2018
Когда читаешь книги Роберта Мартина про чистый код или про хороших программистов, сразу хочется покрыть весь свой код модульными тестами, встать на путь TDD и никогда с него не сходить. Выступления про вред интеграционных тестов еще больше укрепляют уверенность в необходимости модульных тестов. Утверждения в книгах и выступлениях кажутся верными, но применение новых практик в ежедневной работе вызывает боль. 
Основные боли с которыми мне приходилось сталкиваться при работе с модульными тестами:
Можно терпеть боль и продолжать применять практики. Можно поддерживать запал, смотря на пирамиду тестирования и повторяя "модульные тесты – основа пирамиды, их должно быть больше всего", – это снизит боль, но не устранит её причину.
Разобраться в причине боли мне помогли книги и статьи Кента Бека – человека, который придумал Extreme Programming и Test Driven Development. Если Роберт Мартин говорит с читателем языком догм: "Настоящий программист должен писать по TDD и точка!", то Кент Бек ведет диалог с читателем и описывает те ценности и принципы, которые привели его к конкретным практикам, в данном случае к TDD. 
Основные принципы из которых появился TDD: продукт должен быть качественным, шаги для решения проблемы должны быть маленькими, процесс разработки должен идти потоком (flow). Именно из-за принципа маленьких шагов TDD ассоциируется с модульными тестами. Причем Кент не говорит таких догм как "тесты не должны ходить в базу данных" или "при тестировании одного объекта все его зависимости должны быть подменены". 
Тесты должны давать вам уверенность в работоспособности продукта и возможность придумывать решение ваших проблем шаг за шагом, не сбивая ваш фокус. Все, больше ничего. Конкретные же практики зависят от конкретной ситуации. 
Если при тестировании можно использовать in-memory базу данных и прогонять сотни тестов за доли секунды – используйте её! Ведь это увеличит уверенность в работоспособности продукта. Если вы не знаете конкретный путь к реализации функциональности, то сделайте первый шаг – напишите самый высокоуровневый тест в тех терминах, в которых вы сейчас понимаете задачу. И если этого теста будет достаточно для реализации функциональности без потери уверенности в ней, то смело его оставляйте. 
Но если вам сложно понимать настройку ваших тестов, и это бьёт по уверенности в работоспособности продукта, то стоит их упростить. Например, перенеся большую часть проверок на уровнь ниже – в более модульные тесты, или создав абстракцию для настройки тестов. Если ваши тесты идут слишком долго и прерывают поток разработки, то можно их ускорить. Причем ускорять можно несколькими способами, например перестать ходить в базу данных или запускать тесты параллельно на нескольких базах. Любой способ хорош, если он не идет вразрез с принципами. 
Не нужно бояться интеграционных тестов, если вам комфортно работать с ними. Если вам комфортно работать с вашими модульными тестами – продолжайте с ними работать. Главное – перестать слепо следовать догмам, прислушиваться к своим ощущениям и рефлексировать, стараясь взглянуть на проблему с нескольких точек зрения.
Открыть комментарии