Мы работаем с системами аналитики веб-приложений от компании Omniture. У меня давно возникло желание запросить текущие данные из дата-центра Omniture для формирования некоторых внутренних отчетов. Omniture при составлении отчетов использует RESTful API, после непродолжительной работы с которым, я решил, что неплохо было бы написать специально для него библиотеку оболочки.
Недавно я прошел курс PHP Testing Bootcamp от Криса Хартджеса, и решил, что хочу написать библиотеку с помощью разработки через тестирование (TDD). Тут я понял, что сталкиваюсь с этим впервые. Кроме того, мне хотелось сделать библиотеку, совместимую с Composer. И для этого мне хватило уикенда. Когда выходные закончились, у меня на руках была почти законченная библиотека, которая требовала лишь внесения небольших изменений. Я многое узнал за эти два дня. Хочу поделиться с вами своим опытом.
Урок первый: TDD на 90% меняет способ программирования кода и на 10% написание тестов
Меня всегда печалил процесс написания тестов — я не мог понять, как писать тесты для так называемых «настоящих приложений». Я понял основы утверждений, но соединить их друг с другом не получается. Проблема такая: чтобы написать тестируемый код, вам нужно иметь слабосвязанный код. И это гораздо легче сказать, чем сделать.
Вот здесь и вступает в игру Закон Деметры. Согласно этому закону «можно взаимодействовать только с ближайшими модулями-«друзьями»». С точки зрения объектно-ориентированного программирования это означает, что код должен быть разбит на куски, которые могут взаимодействовать только с теми фрагментами, с которыми они связаны непосредственно. Этой теме посвящено несколько статей. Очень хорошо закон описан в книге Криса Building Testable PHP Application.
Урок второй: Понимание Mock Objects играет важную роль
Однажды я использовал несколько фиктивных объектов и действительно начал получать результаты тестирования (по крайней мере, я так думаю). Могу честно сказать, что понимание важности фиктивных объектов отсутствует в моем предыдущем образовании, связанном с тестированием. И здесь мне очень помогла Mockery library, которая позволяет действительно быстро писать фиктивные объекты.
Урок третий: Вы тратите почти вдвое больше времени на написание тестируемого кода
Начав программировать, я заметил такую вещь: написание тестов отнимает больше времени, чем программирование кода. Сначала я связывал это с моей неопытностью в написании тестов, попутно выясняя, как проверить определенные сценарии и т.д. Но я даже представить себе не мог, что увеличение времени, отводимого на тестирование, значительно увеличивает и время на разработку приложения.
И вы знаете что? Это хорошо — ведь я осознал, что допускал много мелких ошибок еще на начальном этапе. Я укрепил код при помощи тестов и получил непробиваемое приложение.
Урок четвертый: из написания тестов очень легко сформировать привычку
Я втянулся уже после нескольких часов программирования. Удивило то, насколько легко оказалась просто взять и забыть про написание тестов. Но тут существует опасность, что, как только ты перестанешь писать тесты в первую очередь, а затем программировать код, чтобы проверить его, ты получить массу ошибок, на избавление от которых потребуется дополнительное время.
Урок пятый: больше рефакторинга при написании тестов
В процессе написания тестов для собственного кода вы начнете лучше понимать, и то, как улучшить код. Во время написания этой библиотеки у меня пару раз возникала мысль, что некоторые запутанные коды я бы написал иначе. Обнаруживая проблемы процесса кодирования еще на начальном этапе, я начал по-настоящему понимать силу тестов.
Итак. Я внес изменения в код и провел тестирование. Я поправил сломавшийся код, который зависел от старой функциональности, ориентируясь на новую функциональность, и все встало на свои места. Было удивительно, как с помощью рефакторинга и тестов можно поставить код на место.
Урок шестой: Наличие проверяемого кода заставило меня задуматься о совместном использовании кода.
Я не видел смысла в разделении кода, который написал. Было очевидно, что библиотека, которую я сделал, содержит меньше ошибок, чем написанная без тестирования. Я могу поделиться этим кодом с другими разработчиками, чтобы помочь им обработать свои собственные данные.
Не знаю, как много людей, которые прочтут этот пост, пожелают воспользоваться моей PHP библиотеке для обработки отчетности Adobe/Omniture Site Catalyst API, но такая возможность есть у каждого. Если хотите, можете вносить свои изменения.
Мне еще много предстоит узнать о написании тестов, но я рад, что некоторые важные вещи начинают доходить до моего сознания. Точно вам говорю: если просто взять и начать писать проверяемый код, то можно получить действительно прочное приложение.