# Тестируйте требуемое поведение, а не случайное

(В оригинале - Test for Required Behavior, not Incidental Behavior)

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

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

Например, сравнение вроде `strcmp` в С или `String.compareTo` в Java требует, чтобы результат был отрицательным, если левая часть меньше правой, положительным, если наоборот и нулевым, если обе части равны. Этот стиль сравнения используется множеством API, включая `comparator` для функции `qsort` в С и `CompareTo` в `Comparable` интерфейсе в Java. И хотя в реализациях очень часто используются значения `+1` и `-1`, считать, что эти значения являются требованием к реализации, будет ошибкой. Написание теста исходя из этого предположения приведет к тому, что ошибочное предположение материализуется.

Подобные вещи происходят с тестами, проверяющими количество пробелов, точное написание слов и другие аспекты форматирования, часто являющиеся случайными. Кроме случаев, когда вы пишете XML-генератор, предлагающий настраиваемое форматирование, количество пробелов не должно быть значимым для итогового результата. Точно также жесткая привязка к позициям элементов GUI снижает возможность дальнейшего изменения. Небольшое и незначимое изменение в реализации или форматировании в результате внезапно становится «убийцей» сборки.

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

Чтобы быть эффективными, тесты должны проверять только контрактные обязательства, а не реализацию. Тестируемый юнит должен рассматриваться как «черный ящик», предоставляющий интерфейс в исполняемом виде. Поэтому старайтесь, чтобы тестируемое поведение было идентичным требуемому.

Автор оригинала - [Kevlin Henney](http://programmer.97things.oreilly.com/wiki/index.php/Kevlin_Henney)
