Добавляли ли вы когда-нибудь модульные тесты в унаследованный код? Насколько сложен был код и насколько сложно все заглушить и имитировать? Стоил ли конечный результат?
Добавляли ли вы когда-нибудь модульные тесты в унаследованный код? Насколько сложен был код и насколько сложно все заглушить и имитировать? Стоил ли конечный результат?
Ответы:
Я обнаружил, что лучший способ - это постепенно добавлять модульные тесты, а не просто вмешиваться и говорить, что теперь мы проведем модульное тестирование приложения.
Итак, если вы собираетесь трогать код для исправления ошибок или рефакторинга, то сначала напишите модульные тесты. Модульные тесты на наличие ошибок помогут доказать, в чем проблема, так как вы можете ее продублировать.
При рефакторинге вы захотите написать модульные тесты, но вы можете обнаружить, что этот тест невозможно написать, поэтому вам может потребоваться найти высокий уровень, который вызывает функцию, которая будет реорганизована, и модульное тестирование этой части. Затем, по мере рефакторинга наступательной функции, напишите свои тесты, чтобы убедиться, что она работает должным образом.
Нет простого способа сделать это.
Этот вопрос может помочь с дополнительными предложениями. Как внедрить модульное тестирование в большую устаревшую (C / C ++) базу кода?
Книга Майкла Фезерса «Эффективная работа с устаревшим кодом» - это целая книга, посвященная этой теме. Майкл заявляет, что часто слишком сложно вводить тесты для унаследованного кода, потому что он не структурирован для тестирования. Больше всего я извлек из книги пару шаблонов под названием «Функции ростков» и «Классы ростков». Функция ростка - это функция, которая инкапсулирует изменения, которые вам необходимо внести в код. Затем вы выполняете модульное тестирование только этих функций. Класс sprout - это та же идея, за исключением того, что новая функциональность содержится в классе.
Да и вообще больно. Вместо этого мне часто приходилось писать интеграционные тесты.
В книге «Искусство модульного тестирования» есть несколько полезных советов по этому поводу. Он также рекомендует книгу « Эффективная работа с устаревшим кодом» ; Последнюю я еще не читал, но она у меня в стопке.
РЕДАКТИРОВАТЬ: Но да, даже минимальное покрытие кода того стоило. Это придало мне уверенности и безопасности при рефакторинге кода.
РЕДАКТИРОВАТЬ: Я прочитал "Эффективная работа с устаревшим кодом", и это отлично.
Также обратите внимание на новый подход в области модульного тестирования устаревшего кода - проект Asis , он вдохновлен проектом ApprovalTests и разделяет его ключевые концепции.
Как упоминалось в этой статье о подходе ApprovalTests :
Часто у вас есть огромный проект устаревшего кода, где у вас вообще нет тестов, но вам нужно изменить код, чтобы реализовать новую функцию или провести рефакторинг. В устаревшем коде интересно то, что он работает! Работает годами, как бы ни писалось. И это очень большое преимущество этого кода. С разрешениями, с помощью только одного теста вы можете получить все возможные выходные данные (HTML, XML, JSON, SQL или любой другой результат) и одобрить, потому что вы знаете - это работает! После того, как вы завершили такой тест и одобрили результат, вам будет намного безопаснее проводить рефакторинг, поскольку теперь вы «заблокировали» все существующее поведение.
Инструмент Asis предназначен для поддержки унаследованного кода посредством автоматического создания и запуска тестов характеристик.
Для получения дополнительной информации см.
Одна альтернатива модульным тестам, также представленная в разделе Эффективная работа с устаревшим кодом, - это тесты характеристик . У меня были интересные результаты с такими тестами. Их легче настроить, чем модульные тесты, поскольку вы тестируете с точки, чем можно тестировать (так называемый шов). Недостатком является то, что, когда тест не проходит, у вас меньше намека на местонахождение проблемы, поскольку тестируемая область может быть намного больше, чем при модульных тестах. Здесь помогает ведение журнала.
Среда модульного тестирования, такая как семейство xUnit, может использоваться для написания тестов характеристик.
В таких тестах, написанных после фактов, утверждения проверяют текущее поведение кода. В отличие от модульных тестов, они не доказывают правильность кода, они просто фиксируют (характеризуют) текущее поведение кода.
Процесс аналогичен TDD:
Тесты не пройдут, если вы измените внешнее поведение кода. Внешнее поведение кода? звучит знакомо ? Да, вот и мы. Теперь вы можете провести рефакторинг кода.
Очевидно, что риск зависит от охвата характеристических тестов.
Взгляните на бесплатную библиотеку утилит модульного тестирования с открытым исходным кодом, ApprovalTests . Если вы разработчик .NET, создатель, Ллевеллин Фалько, снял серию видеороликов, демонстрирующих, как он использует ApprovalTests для улучшения модульного тестирования как нового, так и устаревшего кода.
Если вы планируете рефакторинг устаревшего кода, создание этих модульных тестов является обязательным. Не беспокойтесь о насмешках или заглушках - беспокойтесь о тестировании входных и выходных данных системы, чтобы ваши изменения или усилия по рефакторингу не нарушили текущую функциональность.
Я не буду вам лгать, модернизировать модульные тесты для устаревшего кода сложно, но оно того стоит.
Некоторое время назад я говорил об идее пирамиды обратных тестов в устаревшем коде на XPDays http://xpdays.com.ua/archive/xp-days-ukraine-2012/materials/legacy-code/
Эта презентация должна ответить на вопрос, почему иногда так важно начинать с интеграционных / функциональных или даже приемочных тестов высокого уровня при работе с устаревшим кодом. А затем медленно, шаг за шагом вводим модульные тесты. Здесь нет примеров кода - извините, но вы можете найти их в книге Майкла Фезерса «Эффективная работа с устаревшим кодом».
Также вы можете проверить Legacy Code Retreat http://www.jbrains.ca/legacy-code-retreat и найти эту встречу в своем районе.