Меня часто просят дать несколько советов о том, с чего начинать написание тестов для PHP. Вы обратились по адресу, так как я представляю себя в качестве эксперта-ниндзя-рок-звезды-сенсея-самоуверенного-эгоиста по этой теме. Я долго боролся с придумыванием ответа, который должен поместиться в 140 символов Twitter-сообщения. И вот недавно мне стало очевидно, что данная тактика не принесет плодов. Излагаю свои мысли о том, как начать работу с тестированием PHP-кода.
Научиться распознавать непроверяемый код
Худшее в мире чувство программист испытывает тогда, когда, сидя за монитором, видит перед собой кусок кода, который писал кто-то другой, а этот код имеет решающее значение для успеха проекта. Многие не удержатся и заметят: если не дай бог ты здесь что-нибудь сломаешь, случится полный крах.
Я не получаю таких предупреждений от своего начальника, однако не понаслышке знаком с тем чувством, которое возникает, когда пытаешься выяснить, что за код перед тобой, и зачем он вообще нужен.
Когда дело доходит до тестирования кода, существуют два принципа, к выполнению которых вы должны стремиться:
- найти способ передать зависимости в коде;
- найти способ сломать код в наименьше возможном модуле.
Следуя этим двум простым, но чрезвычайно трудно реализуемым идеям, вы получите в конечном итоге код, для которого писать тесты становится простейшей задачей, тогда вы будете проводить тестирование, не задумываясь.
Откажитесь от вызовов статических методов. Избавьтесь от этих частных и защищенных методов. Остановите создание новых объектов внутри метода. Подумайте о передаче данных, а не объектов. Убедитесь, что ваши методы имеют мало или не имеют вообще побочных эффектов. Отделите ваш источник данных от кода, который манипулирует его результатами. Что еще более важно, разберитесь в том, почему все эти вещи являются препятствиями на пути к легко проверяемому коду.
Короче говоря: сделайте все необходимое, несмотря на то, что кто-то назовет это пустой тратой времени. Я говорю вам, не слушайте всяких парней, а вместо этого просто расслабьтесь и работайте над очередным проектом, пишите тесты, которые позволяют вам уходить домой с работы вовремя.
Продолжайте изучать язык
Тесты представляют собой обычный код. Вывод — продолжайте учиться лучше писать PHP-код. Многое на PHP Sadness может помочь нам в этом. Обязательно изучите iterator drinking game.
В общем, чем больше вы знаете о языке, тем больше вероятность того, что вы узнаете, как решать задачи базовой функциональности вместо постоянного внедрения в код решений, которые Вы написали сами.
Объединение юнитов кода
Я уже высказывался в других статьях по поводу UNIX-философии. Для нетерпеливых, речь в них шла о создании небольших специализированных юнитов кода с их последующим соединением. Так можно добиться удивительных вещей.
Если вы когда-либо искали в сети способы сделать что-то из командной строки в различных версиях Linux-дистрибутивов, вы поймете, что я имею в виду. “Take sed and cat and awk and grep and pipe it through cut and then to sort and you will get exactly what you want.”
Такого рода вещи прекрасно вписываются в концепцию написания небольших модулей легко проверяемого кода.
Начните задавать вопрос «Как я собираюсь проверить это?»
Это первый вопрос, который я задам сам себе, когда столкнусь с проблемой, решаемой с помощью кода. С этого единственного, но чрезвычайно важного вопроса начинаются все лучшие практики, которые связаны с построением хорошо проверяемого кода.
Чтобы создать автоматизированные тесты для определенного набора функциональных возможностей, хорошенько проанализируйте проблему, которую вы пытаетесь решить.
Я не говорю что, у каждой проблемы есть тестируемое решение. Но любая проблема, где ожидаемые результаты, основываются на известных начальных данных, — это сценарий, который можно протестировать. Запросы к базе данных, Сторонние API, Маршрутизация запросов, Fizz Buzz — все эти вещи мы можем проверить.
Тесториентированная разработка основана на использовании инструментов, как способе создания простых, легко проверяемых и изменяемых API и интерфейсов.
Добавление новых возможностей превращается в совершенно простой процесс, включающий в себя:
- разработку новых функций;
- написание тестов для этих новых функций;
- написание код, во время тестирования;
- своевременный уход домой.
Не используйте код без доказательств его исправности
Конечно, у вас нет никаких тестов ПРЯМО СЕЙЧАС. Но я уверен, что у вас есть ошибки в коде, которые можно исправить. Напишите тесты, чтобы убедиться, что ошибка существует. Я уверен, что вы найдете ваш код никак не модульным или проверяемым, как вы думали раньше.
После того как вы увидели ошибку, работайте над кодом до ее устранения. Затем используйте обновленный код в разработке. Повторяйте операции, пока не получите высокоориентированный набор тестов. Это то, что я называю Тестированием в реальных условиях.
Итак, убедитесь, что ничего, из того что не проверено, не используется в разработке.
Нет ручной работе
Это 2-й год 2-го десятилетия 21-го века. В интернете полно инструкций о том, как автоматизировать все, что угодно.
Chef. Puppet. Shell-скрипты. Jenkins. Travis. Виртуальные серверы. Изучите эти вещи. Используйте их, и вы будете благодарить меня. Отправьте мне деньги через PayPal — этого будет достаточно. Автоматизируйте все, что вы делаете вручную, а затем выясните, есть ли способы автоматизировать и автоматизацию. Вы можете быть удивлены.
Прекратите использовать инструменты без тестов
Я отношусь к любому PHP-инструменту, который не имеет собственного набора тестов, как к черному ящику — с некоторым недоверием. Черный ящик — не та вещь, на которую можно положиться, когда ситуация выходит из-под контроля. Любой код, который вы не можете легко проверить, надо считать подозрительным и опасным. Я чувствую то же самое даже по отношению к коду, который сам написал, так что представьте, что я должен думать о вещах написанных другими людьми.
Всегда перепроверяйте, если все правильно
Интеграционные тесты — обман. Юнит-тесты не исправляют ошибки. Достаточно простой код не требует испытаний. Парное программирование — обременительная практика. PHP — отстой. Мобильные приложения — будущее. Документация — после сделанной работы. Никто не любит разработчика, который задает слишком много вопросов. Вы работаете в реальном мире, где результат имеет значение. Асинхронные вызовы всегда приводят к плохим последствиям.
Не все вышеперечисленное справедливо. Единственный способ узнать для себя — правда это или ложь — испытать на собственном опыте.