Разработка через тестирование на простом примере

Перевод
0
4865
Добавить в избранное

Разработка через тестирование начинается с юнит-тестов, а не с кода. Из части Agile она доросла до самостоятельной дисциплины.


Разработка через тестирование на простом примере

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

Тогда зачем тратить на них время?

Разработка через тестирование на простом примере

Для метода TDD ответ очевиден: сегодняшние вложения в тесты дадут вознаграждение завтра при добавлении новой функциональности и рефакторинге. Метод предлагает писать юнит-тесты перед кодом. Идея появилась в середине 1990-х, а в 2003 опубликовали книгу Экстремальное программирование. Она объясняет понятие непрерывного рефакторинга для улучшения кода продукта.

Принципы разработки через тестирование

Методология представляет собой структурированную практику. Она позволяет получить чистый код и модифицировать его благодаря совмещению программирования, юнит-тестирования и рефакторинга. У методологии есть три фазы:

  • Красная. Код не компилируется? Пишем юнит-тест.
  • Зелёная. Реализация пишется в сжатые сроки. Появилось чистое и простое решение? Выполняйте его. В другом случае продукт будет улучшаться пошагово. Главная цель – получить зелёный цвет для юнит-тестов.
  • Рефакторинг. Не пренебрегайте данным этапом – он устраняет повторения и вводит возможность изменять архитектуру. Фаза не затрагивает поведение программы.

Три ступени реализуются пятью этапами.

Разработка через тестирование на простом примере

Цикл занимает до 10 минут и повторяется до покрытия функциональности юнит-тестами. Кажется, что всё просто. Однако шаги должны выполняться с предельной строгостью для использования преимуществ методологии. Соблюдайте правила, и получите структурированный код. Продукт будет соответствовать необходимым принципам (KISS -–Keep it simple, stupid) без реализации ненужных функций (DRY – Don’t Repeat Yourself) благодаря непрерывному рефакторингу.

Чистые тесты

TDD – это не чудо, ведущее к оптимальному набору юнит-тестов без усилий. Помните, что в этой практике код продукта и тесты одинаково важны!

Чистый тест соблюдает 5 правил:

  • Скорость: он работает быстро для частых запусков.
  • Независимость: не зависят друг от друга.
  • Повторность:  воспроизводится в любой среде.
  • Самопроверка:  возвращает результат (Неудача или Успех) для быстрого и лёгкого заключения.
  • Своевременность: пишется в подходящий момент.

Поменяйте мышление

Разработка через тестирование – отдельная парадигма. Во время обучения растут навыки программиста и преимущества подхода. Рассматривайте методику как вклад в будущее. Изменения затрагивают документацию приложения и юнит-тестов, представляющих исполняемые спецификации. Тесты используются для проверки исполнения требований и описывают их. Большую трудность для программиста составляет создание дорожной карты для сложной функциональности в форме запланированных тестов.

Методология обнаруживает баги на ранних стадиях, что снижает затраты на поиск решения. 80% – это минимум покрытия кода серией юнит-тестов. Следовательно, разработчик уверенно приступает к рефакторингу и постоянному улучшению.

Выбирайте правильные инструменты

Eclipse с нативной поддержкой JUnit – явное преимущество. Плагины MoreUnit и Infinitest рекомендуется использовать в управлении юнит-тестами. Последние выполняют тесты при каждом изменении кода автоматически, что упрощает циклы обратной связи – часть непрерывного юнит-тестирования. В повторяющемся цикле методологии, использование шаблонов кода для юнит-тестов экономит время.

Разработка через тестирование в действии

Решим специфичную задачу. Возьмём проблему преобразования арабских чисел в римские.

Сначала напишем класс RomanNumeralTest. Он содержит серии юнит-тестов программы. Первое требование – значение «1» выдаёт римскую «I»:

При запуске получим ошибку компиляции:

Разработка через тестирование на простом примере

Продолжайте писать код продукта для прохождения теста. Для этого ставим курсор в месторасположение класса RomanNumeral и нажимаем Ctrl+1  – сочетание горячих клавиш Eclipse. Оно предложит быстрое исправление для создания пустого класса RomanNumeral. Аналогичным способом пишем intToRoman – простейший метод, достаточный для возвращения значения «I»:

Тест выполнится. Двигайтесь по циклу.

Разработка через тестирование на простом примере

Сейчас мы входим в фазу рефакторинга. Она пройдёт быстро потому, что в коде нет повторений и нечего улучшать. Цикл начинается с добавления нового теста:

Для успешного прохождения измените метод intToRoman класса RomanNumeral:

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

Тесты по-прежнему имеет зелёный цвет успеха. Мы расширяем их дополнительным требованием – числом 3, которое даёт римскую «III». Это делает неудачными текущие юнит-тесты. Для проверки пишем следующее:

На шаге рефакторинга код улучшается с помощью цикла. Он уменьшает значения арабских чисел и добавляет полосу римских:

Мы обнаруживаем, что алгоритм не поддерживает римскую X. Для этого добавим обработку арабской десятки:

Тест выполняется, а рефакторинг не нужен. Значение 10 и его римское представление XX потребуют ещё один тест. Он «сломает» все предыдущие. Пишем следующий код:

Он пройдёт серию тестов. Фаза рефакторинга позволяет нам вернуться на предыдущий шаг для оптимизации алгоритма преобразования римской X. Заметно, что использование цикла будет эффективнее условий if / else if. Код принимает следующий вид:

Код успешно пройдёт серию тестов. Фаза рефакторинга позволяет нам вернуться на предыдущий шаг для оптимизации алгоритма преобразования римской X. Заметно, что использование цикла будет эффективнее условий if / else if. В итоге код принимает следующий вид:

Junit горит зелёным, а рефакторинг не изменил внутренне поведение метода. Рассмотрев код продукта, мы заметим, что задачи для «I» и «X» выполняются одним способом. У нас появилась идея нового дизайна алгоритма: две таблицы, связанные индексами и содержащие римские и арабские цифры соответственно.

С помощью 30 юнит-тест не сломать, поэтому необязательно изменять код продукта. Для чисел 11 и 33, которые образуются римскими цифрами X и I алгоритм также остаётся функциональным. К неудаче в соответствующем юнит-тесте приведёт «V». Пора начинать цикл разработки через тестирование заново! Первое решение – добавить «V» и её арабский эквивалент в таблицы, и проверить алгоритм. Тесты проходят? Тогда это правильное решение. Во время рефакторинга возникает вопрос: не лучше ли заменить две индексированные таблицы на Java Map? Значения упорядочиваются путём двух взаимосвязанных циклов, текущее решение предпочтительнее потому, что оно проще соответствует принципам KISS.

Разработка через тестирование продолжается и мы завершаем серию юнит-тестов.

Разработка через тестирование на простом примере

После 10 шага получаем следующие таблицы:

ARABIC_DIGITS = {1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1};
ROMAN_DIGITS = {“M”,”CM”,”D”,”CD”,”C”,”XC”,”L”,”XL”,”X”,”IX”,”V”,”IV”,”I”};

Добавление новых тестов с такими арабскими цифрами, как 1954 и 3949 не потребует никаких изменений метода intToRoman в коде продукта. Серия полученных юнит-тестов покрывает код максимально.

Разработка через тестирование на простом примере

Заключение

Знакомство с разработкой через тестирование показало силу этой практики. Смена парадигмы начинается с обучения и завершается ростом производительности разработчика.

Ещё одно упражнение: добавьте метод обратного преобразования в рассмотренную проблему с римскими и арабскими числами. Используйте разработку через тестирование. Практика – средство прогресса!

Что вы думаете по поводу такого тестирования?

Хотите получать больше интересных материалов с доставкой?

Подпишитесь на нашу рассылку:

И не беспокойтесь, мы тоже не любим спам. Отписаться можно в любое время.




Добавить комментарий