Добавление модульных тестов в устаревший код [закрыто]

79

Добавляли ли вы когда-нибудь модульные тесты в унаследованный код? Насколько сложен был код и насколько сложно все заглушить и имитировать? Стоил ли конечный результат?

BuckeyeПрограммное обеспечениеGuy
источник
4
Я проверю «Эффективная работа с устаревшим кодом». Надеюсь, это даст мне хорошие советы о том, как писать оболочки для всех этих статических зависимостей!
BuckeyeSoftwareGuy,

Ответы:

57

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

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

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

Нет простого способа сделать это.

Этот вопрос может помочь с дополнительными предложениями. Как внедрить модульное тестирование в большую устаревшую (C / C ++) базу кода?

Джеймс Блэк
источник
8
+1 для постепенного добавления тестов.
TrueWill
42

Книга Майкла Фезерса «Эффективная работа с устаревшим кодом» - это целая книга, посвященная этой теме. Майкл заявляет, что часто слишком сложно вводить тесты для унаследованного кода, потому что он не структурирован для тестирования. Больше всего я извлек из книги пару шаблонов под названием «Функции ростков» и «Классы ростков». Функция ростка - это функция, которая инкапсулирует изменения, которые вам необходимо внести в код. Затем вы выполняете модульное тестирование только этих функций. Класс sprout - это та же идея, за исключением того, что новая функциональность содержится в классе.

Филип Нган
источник
10

Да и вообще больно. Вместо этого мне часто приходилось писать интеграционные тесты.

В книге «Искусство модульного тестирования» есть несколько полезных советов по этому поводу. Он также рекомендует книгу « Эффективная работа с устаревшим кодом» ; Последнюю я еще не читал, но она у меня в стопке.

РЕДАКТИРОВАТЬ: Но да, даже минимальное покрытие кода того стоило. Это придало мне уверенности и безопасности при рефакторинге кода.

РЕДАКТИРОВАТЬ: Я прочитал "Эффективная работа с устаревшим кодом", и это отлично.

TrueWill
источник
4
+1 за «Эффективная работа с устаревшим кодом»: полный отличных советов; на самом деле его стоит прочитать даже для сред с нуля, так же как и отличный ресурс по созданию кода для тестирования.
itowlson
1
+1 за идею замены модульных тестов на интеграционные. При правильном издевательстве первые бывают достаточно хороши, довольно часто
DVK
7

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

Как упоминалось в этой статье о подходе ApprovalTests :

Часто у вас есть огромный проект устаревшего кода, где у вас вообще нет тестов, но вам нужно изменить код, чтобы реализовать новую функцию или провести рефакторинг. В устаревшем коде интересно то, что он работает! Работает годами, как бы ни писалось. И это очень большое преимущество этого кода. С разрешениями, с помощью только одного теста вы можете получить все возможные выходные данные (HTML, XML, JSON, SQL или любой другой результат) и одобрить, потому что вы знаете - это работает! После того, как вы завершили такой тест и одобрили результат, вам будет намного безопаснее проводить рефакторинг, поскольку теперь вы «заблокировали» все существующее поведение.

Инструмент Asis предназначен для поддержки унаследованного кода посредством автоматического создания и запуска тестов характеристик.

Для получения дополнительной информации см.

завг
источник
Как это не набрать больше голосов? Если репо делает то, что утверждает, это должен быть выбранный ответ.
lolololol ol
Кстати, имеет ли он дело с побочными эффектами в функциях? Даже возможно ли решить эту проблему?
lolololol ol
5

Одна альтернатива модульным тестам, также представленная в разделе Эффективная работа с устаревшим кодом, - это тесты характеристик . У меня были интересные результаты с такими тестами. Их легче настроить, чем модульные тесты, поскольку вы тестируете с точки, чем можно тестировать (так называемый шов). Недостатком является то, что, когда тест не проходит, у вас меньше намека на местонахождение проблемы, поскольку тестируемая область может быть намного больше, чем при модульных тестах. Здесь помогает ведение журнала.


Среда модульного тестирования, такая как семейство xUnit, может использоваться для написания тестов характеристик.

В таких тестах, написанных после фактов, утверждения проверяют текущее поведение кода. В отличие от модульных тестов, они не доказывают правильность кода, они просто фиксируют (характеризуют) текущее поведение кода.

Процесс аналогичен TDD:

  • написать тест для части кода
  • выполнить это - провал
  • исправить тест из наблюдаемого поведения кода
  • выполнить - пройти
  • повторение

Тесты не пройдут, если вы измените внешнее поведение кода. Внешнее поведение кода? звучит знакомо ? Да, вот и мы. Теперь вы можете провести рефакторинг кода.

Очевидно, что риск зависит от охвата характеристических тестов.

филант
источник
5

Взгляните на бесплатную библиотеку утилит модульного тестирования с открытым исходным кодом, ApprovalTests . Если вы разработчик .NET, создатель, Ллевеллин Фалько, снял серию видеороликов, демонстрирующих, как он использует ApprovalTests для улучшения модульного тестирования как нового, так и устаревшего кода.

Линн Лангит
источник
4

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

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

Эндрю Хэйр
источник
Я начал создавать модульные тесты для устаревшего кода, над которым я работал. Однако я понял, что пишу интеграционные тесты, а не модульные тесты, потому что я создаю реальные данные и вставляю их в базу данных. Я не вижу способа создать чистые макеты и заглушки для этого устаревшего кода, потому что он вообще не структурирован для тестирования.
Vin
1

Некоторое время назад я говорил об идее пирамиды обратных тестов в устаревшем коде на XPDays http://xpdays.com.ua/archive/xp-days-ukraine-2012/materials/legacy-code/

Эта презентация должна ответить на вопрос, почему иногда так важно начинать с интеграционных / функциональных или даже приемочных тестов высокого уровня при работе с устаревшим кодом. А затем медленно, шаг за шагом вводим модульные тесты. Здесь нет примеров кода - извините, но вы можете найти их в книге Майкла Фезерса «Эффективная работа с устаревшим кодом».

Также вы можете проверить Legacy Code Retreat http://www.jbrains.ca/legacy-code-retreat и найти эту встречу в своем районе.

Streser
источник