Год назад у меня был интересный разговор с моим лучшим другом Алексом о проверке кода. Он сказал, что когда он делает обзор кода, он всегда начинает с тестов. Он использует эту технику, чтобы понять, что на самом деле делает код, как он себя ведет и какие функции он покрывает.

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

Когда вы хотите реализовать функцию, вы переводите одно требование на варианты использования. Вы переводите один вариант использования в тестовые примеры. Вы реализуете эти тестовые примеры в своем производственном коде.

Если вы занимаетесь TDD, то вы следуете Трем законам TDD. Вот три закона:

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

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

Поведение кода ограничено тестовыми примерами.

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

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

Если тест тратит слишком много времени на имитацию цепочки вызовов методов отдельного объекта, то вы можете быть уверены, что нарушается Закон Деметры. Если нарушается закон Деметры, можно быть уверенным, что код страдает проблемами инкапсуляции. И все же я знаю, что даже не глядя на код, я знаю это, просто глядя на структуру теста.

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

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

Кстати, тест тоже код

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

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

Дальнейшее чтение

  1. Циклы TDD
  2. Закон Деметры в эпоху микросервисов
  3. Важность командной культуры
  4. Рефакторинг: улучшение дизайна существующего кода Мартин Фаулер и Кент Бек