Перемещение существующего кода в Test Driven Development - PullRequest
35 голосов
/ 03 октября 2008

Недавно обнаружив этот метод разработки, я нахожу его довольно хорошей методологией. Итак, для моего первого проекта у меня есть небольшой код DLL (в C # .NET, для чего он стоит), и я хочу сделать набор тестов для этого кода, но я немного растерялся относительно того, как и с чего начать.

Я использую NUnit и VS 2008, любые советы о том, с каких классов начинать, для чего писать тесты, и любые советы о том, как перейти к переносу кода в разработку на основе тестов, будут очень благодарны. .

Ответы [ 5 ]

54 голосов
/ 03 октября 2008

См. Книгу Эффективная работа с устаревшим кодом Майкла Фезерса.

Таким образом, много работы по преобразованию существующего кода в тестируемый и протестированный код; Иногда это слишком много работы, чтобы быть практичным. Это зависит от того, насколько велика кодовая база и насколько различные классы и функции зависят друг от друга.

Рефакторинг без тестов приведет к изменениям в поведении (то есть к ошибкам). И пуристы скажут, что это не совсем рефакторинг из-за отсутствия тестов, чтобы проверить, что поведение не меняется.

Вместо того, чтобы добавлять тест по всем направлениям сразу ко всему вашему приложению, добавляйте тесты, когда вы работаете в области кода. Скорее всего, вам придется снова вернуться в эти «горячие точки».

Добавьте тесты снизу вверх: проверьте правильность небольших независимых классов и функций.

Добавление тестов сверху вниз: тестируйте целые подсистемы как черные ящики, чтобы увидеть, меняется ли их поведение с изменениями в коде. И поэтому вы можете пройти через них, чтобы узнать, что происходит. Такой подход, вероятно, принесет вам наибольшую пользу.

Сначала не беспокойтесь о том, что такое «правильное» поведение, когда вы добавляете тесты, ищите, чтобы обнаружить и избежать изменений в поведении. Большие, непроверенные системы часто имеют внутреннее поведение, которое может показаться неправильным, но от этого зависят другие части системы.

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

Если в программе нет внутренних интерфейсов, линий, которые определяют границу между одной подсистемой / слоем и другой, то вам, возможно, придется попытаться ввести их и протестировать на них.

Кроме того, автоматические рамки для насмешек, такие как Rhinomocks или Moq , могут помочь в этом. Я действительно не нашел их в коде, разработанном для тестируемости.

10 голосов
/ 03 октября 2008

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

Я также нашел Разработка через тестирование по примерам и Прагматическое модульное тестирование: в C # с NUnit - достойное введение в модульное тестирование в этой среде.

Один из простых подходов к запуску TDD - начать писать тесты первыми, начиная с этого дня, и убедиться, что всякий раз, когда вам нужно прикоснуться к существующему (не проверенному модулем) коду, вы пишете проходные тесты, которые проверяют существующее поведение системы перед тем, как изменить его, чтобы можно было повторно запустить эти тесты, чтобы повысить уверенность в том, что вы ничего не сломали.

9 голосов
/ 03 октября 2008

Я называю это «Обратный инжиниринг, управляемый тестом».

Начните «снизу» - каждый класс может быть изучен отдельно и для него написан тест. Если есть сомнения, угадайте.

Когда вы делаете обычный TDD в прямом направлении, вы относитесь к тесту как к священному и предполагаете, что код, вероятно, не работает. Иногда тест неверен, но ваша стартовая позиция - это код.

Когда вы выполняете TDRE, код является священным - пока вы не сможете доказать , что в коде есть давняя ошибка. В обратном случае вы пишете тесты вокруг кода, настраивая тесты, пока они не работают, и утверждаете, что код работает.

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

Чтобы судить, действительно ли код неправильный, вам также нужно начать сверху с общих тестовых примеров. Живые данные, которые действительно работают, - это начало. Кроме того, живые данные, которые выдают любую из известных ошибок, также являются хорошим началом.

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

4 голосов
/ 03 октября 2008

Тестируемый код легко определить - по сопровождающим тестам. Если они есть, они должны быть проверены. Если их нет - предположим обратное. ;)

Тем не менее: разработка через тестирование (TDD) - это не столько стратегия тестирования, сколько стратегия проектирования. Тесты, которые вы пишете, в первую очередь помогают в разработке интерфейса ваших классов, а также в правильном определении объема ваших классов (или подсистем).

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

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

1 голос
/ 03 октября 2008

Ваша DLL предоставляет какую-то услугу. Что вы должны сделать для каждого сервиса, чтобы получить этот сервис, какие параметры вы должны передать, чтобы получить этот сервис, как вы узнали бы, что запрошенный сервис был правильно выполнен?

Получив ответы на эти вопросы, вы можете написать первый тест. Такие тесты скорее будут называться Тесты характеристик , чем модульные тесты, но, вероятно, их будет легче написать, чем модульные тесты, если бы DLL не была разработана с использованием TDD.

Тесты характеристик также обсуждаются в книге М. Перса «Эффективная работа с устаревшим кодом», которая рекомендуется в других ответах.

Кроме того, обязательно добавьте неудачный тест, прежде чем добавлять новую строку кода.

...