Опытный разработчик не так давно зашёл в .Net и поставил цель получить сертификат Microsoft. Свой ежедневный прогресс он описывает на канале .Net Разработчик. Заметки об изученном материале, советы по повышению производительности и поддержке мотивации, ин
День 1186. #ЗаметкиНаПолях
Код или Тесты: Что Рефакторить?
Сегодня рассмотрим, как рефакторить производственный код, если у вас нет достаточного покрытия тестами.
Все мы иногда работаем над устаревшими проектами. Фактически, они даже более распространены, чем разработка с нуля. Устаревшие проекты печально известны своим «качеством» кода, как производственного, так и тестового. Некоторые проекты могут вообще не иметь тестов. Как провести рефакторинг такого проекта?
Для безопасного рефакторинга у вас должны быть тесты, чтобы гарантировать, что ваш рефакторинг ничего не сломает. Но как внедрить тесты в проект с тесно связанным, не тестируемым кодом? Если бы код был хорошим и его можно было тестировать, вам не нужно было бы его рефакторить.
Это проблема курицы и яйца в старых проектах:
- Нужны тесты, чтобы убедиться, что рефакторинг прошёл успешно.
- Нужно провести рефакторинг кода, чтобы сделать его пригодным для тестирования.
Обойти эту проблему невозможно: тестовый и рабочий код неразрывно связаны; невозможно создать хорошие тесты, не вложив усилий в кодовую базу, которую они охватывают.
Чтобы преодолеть эту проблему, надо начать со сквозных и интеграционных тестов.
Сквозные тесты полностью имитируют конечного пользователя. Например, если ваше приложение представляет собой веб-сайт, сквозные тесты проверяют его через веб-интерфейс. Как правило, их мало, и они должны применяться только к наиболее важному функционалу: функциям, в которых вы никогда не хотите видеть каких-либо ошибок, и только если вы не можете получить такую же степень защиты с помощью модульных или интеграционных тестов.
Большую часть работы обычно выполняют модульные тесты, потому что их дешевле писать и поддерживать. Однако в устаревшем проекте сквозные тесты являются единственным доступным вариантом, потому что это единственный тип тестов, который не требует изменений в коде (поскольку они взаимодействуют с приложением, используя тот же интерфейс, что и обычные пользователи). Сквозные тесты также обладают наибольшей устойчивостью к рефакторингу и не вызывают ложных срабатываний из-за ваших действий по рефакторингу.
В некоторых устаревших проектах также есть золотая середина, где вы можете писать интеграционные тесты вместо сквозных. Это проекты, которые имеют хотя бы некоторую степень разделения ответственности. Например, API с беспорядочным кодом, в котором всё же есть контроллеры. Вы можете протестировать эти контроллеры вместо полноценного вызова конечных точек API из отдельного процесса. Полученные тесты будут интеграционными, и их будет легче поддерживать, чем сквозные тесты.
Хорошая новость, что большое количество сквозных и интеграционных тестов — временные. Как только вы начнёте рефакторинг, замените сквозные тесты интеграционными, а интеграционные - модульными.
Итак, путь к рефакторингу устаревшего кода таков:
1. Определите небольшую связную область в приложении, которую можно было бы отрефакторить относительно быстро и без разрушения остального кода.
2. Покройте эту область сквозными или интеграционными тестами.
3. Выполняйте рефакторинг, разделив бизнес-логику и обязанности по оркестровке.
4. Покройте бизнес-логику юнит-тестами; оркестровку - интеграционными тестами.
5. Удалите сквозные тесты (если они не обеспечивают дополнительного тестового покрытия).
6. Помните, что адекватное покрытие модульными тестами невозможно без качественной кодовой базы.
Источник: khorikov.org/posts/2…refactor