Читаем Экстремальное программирование. Разработка через тестирование полностью

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

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

Сколько должно быть тестов?

Насколько емкой должна быть обратная связь? Рассмотрим простую задачу: дано три целых числа, обозначающих длины сторон треугольника. Метод должен возвращать:

• 1 – в случае, если треугольник равносторонний;

• 2 – в случае, если треугольник равнобедренный;

• 3 – в случае, если треугольник не равносторонний и не равнобедренный.

Если длины сторон заданы некорректно (невозможно построить треугольник со сторонами заданной длины), метод должен генерировать исключение.

Вперед! Попробуйте решить задачу (мое решение, написанное на языке Smalltalk, приведено в конце данного подраздела).

Это отчасти напоминает игру «Угадай мелодию» («Я могу закодировать задачу за четыре теста!» – «А я – за три!» – «О’кей попробуйте».) Для решения задачи я написал шесть тестов, а Боб Биндер в своей книге Testing Object-Oriented Systems[29] («Тестирование объектно-ориентированных систем») для этой же самой задачи написал 65 тестов. Сколько на самом деле нужно тестов? Вы должны решить это сами, исходя из собственного опыта и рассуждений.

Когда я думаю о необходимом количестве тестов, я пытаюсь оценить приемлемое среднее время между сбоями (MTBF, Mean Time Between Failures). Например, в языке Smalltalk целые числа ведут себя как целые числа, а не как 32-битные значения. Иными словами, максимально возможное значение целого числа ограничивается не тридцатью двумя битами, а объемом памяти. Это означает, что вы можете обойтись без тестирования MAXINT. Безусловно, определенный предел существует, ведь теоретически можно создать целое число, для хранения которого не хватит имеющейся памяти. Но должен ли я тратить время на написание и реализацию теста, пытающегося заполнить память невероятно огромным целым числом? Как это повлияет на MTBF моей программы? Если я в обозримом будущем не собираюсь иметь дело с треугольниками, размер сторон которых измеряется такими числами, значит, моя программа не станет существенно менее надежной, если я не реализую такой тест.

Имеет ли смысл писать тот или иной тест? Это зависит от того, насколько аккуратно вы оцените MTBF. Если обстоятельства требуют, чтобы вы увеличили MTBF от 10 лет до 100 лет, значит, имеет смысл уделить время для разработки самых маловероятных и чрезвычайно редко возникающих ситуаций (если, конечно, вы не можете каким-либо иным образом доказать, что подобные ситуации никогда не могут возникнуть).

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

TriangleTest

testEquilateral

self assert: (self evaluate: 2 side: 2 side: 2) = 1

testIsosceles

self assert: (self evaluate: 1 side: 2 side: 2) = 2

testScalene

self assert: (self evaluate: 2 side: 3 side: 4) = 3

testIrrational

[self evaluate: 1 side: 2 side: 3]

on: Exception

do: [: ex | ^self].

self fail

testNegative

[self evaluate: -1 side: 2 side: 2]

on: Exception

do: [: ex | ^self].

self fail

testStrings

[self evaluate: ‘a’ side: ‘b’ side: ‘c’]

on: Exception

do: [: ex | ^self].

self fail

evaluate: aNumber1 side: aNumber2 side: aNumber3

| sides |

sides:= SortedCollection

with: aNumber1

with: aNumber2

with: aNumber3.

sides first <= 0 ifTrue: [self fail].

(sides at: 1) + (sides at: 2) <= (sides at: 3) ifTrue: [self fail].

^sides asSet size

Когда следует удалять тесты?

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

Перейти на страницу:

Все книги серии Библиотека программиста

Программист-фанатик
Программист-фанатик

В этой книге вы не найдете описания конкретных технологий, алгоритмов и языков программирования — ценность ее не в этом. Она представляет собой сборник практических советов и рекомендаций, касающихся ситуаций, с которыми порой сталкивается любой разработчик: отсутствие мотивации, выбор приоритетов, психология программирования, отношения с руководством и коллегами и многие другие. Подобные знания обычно приходят лишь в результате многолетнего опыта реальной работы. По большому счету перед вами — ярко и увлекательно написанное руководство, которое поможет быстро сделать карьеру в индустрии разработки ПО любому, кто поставил себе такую цель. Конечно, опытные программисты могут найти некоторые идеи автора достаточно очевидными, но и для таких найдутся темы, которые позволят пересмотреть устоявшиеся взгляды и выйти на новый уровень мастерства. Для тех же, кто только в самом начале своего пути как разработчика, чтение данной книги, несомненно, откроет широчайшие перспективы. Издательство выражает благодарность Шувалову А. В. и Курышеву А. И. за помощь в работе над книгой.

Чед Фаулер

Программирование, программы, базы данных / Программирование / Книги по IT

Похожие книги