Когда unit-тестировать?!

В который раз убедился, что многие разработчики не умеют писать элементарные unit тесты. В связи с чем я и решил сделать слепок того, что знаю о unit тестировании. Для начала хотелось бы поговорить о том, что должна представлять из себя легко тестируемая система.
Как ни странно это прозвучит, но unit тестировать нужно, когда в системе есть эти самые юниты, которые нужно протестировать. Юнит — это единичная, неделимая операция.
Чем больше юнит может, тем меньше он является юнитом. В ООП единственным достойным претендентом на звание юнита является метод. Соответственно разработка unit тестов требует наиболее "низкого" уровня проектирования системы — проектирования на уровне методов. Такое проектирование очень редко делается на стадии дизайна функциональности или компонента и остается на совести разработчика. Подобный подход вполне оправдан, иначе дизайн-документы в течении первых месяцев разработки превратились бы в многотомные фолианты. 
Проектирование на уровне методов — это тема отдельной книги, однако, лично для себя я выделил следующие принципы проектирования, ориентированного на unit тестирование:

Краткость
Является логическим следствием принципа "функциональной связности" (в узких кругах широко известен как functional cohesion). Однако, для простоты и в качестве руководства к действию я бы сказал именно "краткость".
Краткость подразумевает выполнение строго определенного действия. В качестве идеализированного примера можно привести языковой оператор.
Краткости проще всего достичь, разбив "крупный" метод на более "мелкие", следующие конкретному функциональному назначению. Например, если метод должен найти значение массива, соответствующее определенному условию, а затем вычислить значение производное от него. У вас уже есть три метода: первый — перебирает массив и ищет значение, второй — производит вычисления, третий — вызывает первые два; и два unit теста — на первый и второй методы. Третий метод в плане unit тестирования ценности не представляет, а только увеличивает покрытие.

Ограниченность влияния
Так же является следствием другого принципа "low coupling". Метод не должен обновлять поля 85-ти близлежащих классов и  впридачу выводить сообщения в stdout. Идеальный для unit тестирования метод не должен изменять состояния вообще, в крайнем случае такое изменение состояния должно производится один раз за все время исполнения метода. 

Простота
Собственно результат применения KISS. Метод хорошо поддающийся тестированию как правило содержит не более 3 ветвей исполнения, говоря попросту в методе не должно быть более трех if/while/else/for и так далее. Достигается путем выноса:
  • логики проверки входных параметров за пределы метода. Например, путем декларативной проверки (Spring Framework предоставляет отличный класс Assert, именно для этих целей)
  • разнообразных операций поиска, проверки, вычисления в утилитный классы и методы
  • методов в "под-методы"
Если система уже написана и ее код не соответствует вышеописанным требованиям, то unit тесты точно не для Вас. Если Вы не собираетесь тратить достаточно времени на проектирование методов и unit тестов, то unit тесты точно не для Вас. Применение unit тестов обязательно требует приведение кода именно к описанному виду. Все остальное будет работать, как метеоролог — "ошибается один раз, но каждый день".

Внимательный читатель наверняка заметил, что все описанное выше, является ни чем иным, как расширенным толкованием перевода слова "unit" — блок, единица на русский язык. Собственно ничего другого о unit тестировании понимать и не нужно. Все остальное уже "обвес" и приходит с опытом.