8 самых необходимых инструментов контроля качества PHP-кода

Процедуры обеспечения качества (Quality Assurance или сокращённо QA) для PHP-кода весьма востребованы, но очень редко применяются на практике.

В мире веб-разработки, где фокус всегда был смещён на прототипирование «на лету» и быстрое развёртывание, качество кода почти никогда не ставится во главу угла. Но недавно мне указали на сайт PHP QA Tools, который ведёт Себастиан Бергманн.

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

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

1. PHPUnit

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

composer global require "phpunit/phpunit=4.1.*"

2. Behat

Behat – это фреймворк, помогающий осуществлять разработку согласно концепции BDD. (Behavior-Driven Development – разработка, основанная на поведении программы, разновидность TDD – Test-Driven Development, разработки, основанной на постоянном тестировании. – Прим. перев.).

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

Scenario: List 2 files in a directory
  Given I am in a directory "test"
  And I have a file named "foo"
  And I have a file named "bar"
  When I run "ls"
  Then I should get:
    """
    bar
    foo
    """

Затем вы пишете классы с методами, реализующими предложения, например:

/** @Given /^I have a file named "([^"]*)"$/ */
    public function iHaveAFileNamed($file)
    {
        touch($file);
    }

А Behat вызывает эти функции и передаёт им аргументы, которые вы задали в кавычках.

Поскольку эти тесты легко понимаются и даже пишутся людьми с минимальной подготовкой, их применение может ощутимо снизить «языковой барьер» между менеджментом и разработчиками. Вот только не совсем понятно, в какую категорию входят эти тесты: TDD или BDD?

BDD или TDD

Существует множество руководств, статей и видеороликов, посвящённых сравнению TDD и BDD, но основная идея, которую можно вынести из них всех, сводится к следующему: BDD – это TDD, доведённое до ума.

BDD – это правильное TDD

Приёмы и инструменты BDD проверяют функционирование вашего приложения в соответствии с контекстом его выполнения. Обе методологии не исключают совместного применения: BDD может использовать отладочные инструменты наподобие тех, что имеются в PHPUnit. Тем не менее, необходимо учитывать главное различие между методологиями, о которых мы говорим:

BDD не покрывает код!

Как же мы узнаем, в какой процедуре или в каком файле у нас ошибка? Какой код мы проверили, а какой ещё надо проверить? Проще говоря, никак (разумеется, если вы не используете отдельные средства, оценивающие покрытие кода).

BDD не предназначен для решения этих задач. Если TDD ориентирован на код, то BDD – на пользователя. Инструменты TDD сообщают вам, к какому результату пришла та или иная функция в вашей программе. BDD проверяет общую функциональность программы: выдаёт ли она ожидаемый результат в ответ на запрос пользователя, и не возникла ли непредвиденная ситуация в ходе выполнения.

Если внешне всё в порядке, тест считается пройденным. Если функция не взаимодействует с пользователем, можно считать её не тестируемой. Просто с точки зрения BDD целое (программа) значит больше, чем его части (процедуры и функции), в то время как с точки зрения TDD никакого целого не существует. Методология BDD не предназначена для приверженцев мелочного контроля.

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

Behat может быть установлен глобально командой:

composer global require behat/behat='~3.0.6'

3. vfsStream

Развивая тему средств тестирования, необходимо упомянуть также vfsStream – эмулятор файловой системы, который поможет заменить настоящую файловую систему при юнит-тестировании приложений, написанных на PHP.

Функция vfsStream проста: замена файловой системы в прототипе веб-приложения. Примеры использования vfsStream, приведённые на странице в вики, говорят сами за себя, а из более сложных функций стоит отметить способность копировать структуру каталогов из реальной файловой системы вместе с атрибутами доступа и файлами (объём которых не должен превышать заданной квоты).

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

4. PHPLOC

Ещё одно детище мистера БергманнаPHPLOC (LOC – Lines Of Code, строки кода – единица измерения производительности труда программиста, столь же популярная, сколь и обманчивая. – Прим. перев.) – утилита, способная генерировать различную статистику о вашем коде: количестве строк, файлов, классов и т. д.

Утилита умеет проходить дерево ревизий в Git, генерировать отчёты за разные периоды и экспортировать их в формат CSV.

PHPLOC может быть установлен командой:

composer global require 'phploc/phploc=*'

и использоваться для любого проекта на любом хостинге. Всё, что для этого нужно – запустить:

phploc FOLDER

где «FOLDER» – папка с проектом, который вы хотите проанализировать.

Разумеется, польза от подобной статистики в лучшем случае сомнительна, но она может быть использована как аргумент в спорах между менеджерами и разработчиками, и я часто вижу на страницах Github, как различные проекты публикуют там красивые графики развития, сформированные при помощи PHPLOC.

Сайт Себастиана Бергманна также упоминает утилиту PHP_Depend. Мне она кажется всего лишь слегка устаревшим и не аккуратно спроектированным конкурентом PHPLOC. Мы решили не указывать её отдельным пунктом – отчасти поэтому, а отчасти потому, что следующим номером нашего списка выступает инструмент, использующий PHP_Depend у себя под капотом.

5. PHP Mess Detector

PHP Mess Detector (обнаружитель беспорядков), будучи установленным, обрабатывает ваш код утилитой PHP_Depend и использует полученные метрики для составления собственных отчётов.

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

PHP Mess Detector может быть установлен командой:

composer global require 'phpmd/phpmd=*'

PHPMD в своей работе руководствуется списком так называемых правил: набором специфических указаний того, как и что искать в исходниках. Есть большое количество предопределённых правил.

Пользователь также может расширить систему, написав собственные правила.

Мы ещё расскажем о PHP Mess Detector более подробно в одной из будущих статей.

6. PHP CodeSniffer

Подобно PHPMD, CodeSniffer осуществляет статический анализ вашего кода. Кроме PHP, этот инструмент проверяет также код CSS и JavaScript.

CodeSniffer всегда был доступен для инсталляции при помощи PEAR. Теперь, когда PEAR уходит в прошлое, есть возможность установить его и при помощи Composer:

composer global require 'squizlabs/php_codesniffer=*'

Использовать CodeSniffer довольно легко, о чём свидетельствует вики проекта. Мы планируем в ближайшее время рассказать вам о том, как интегрировать CodeSniffer в свой проект.

7, 8. DCD и CPD

Ещё две утилиты авторства господина Бергманна, Dead Code Detector и Copy-Paste Detector, помогают выявить не используемый код (методы и функции, объявленные, но не используемые в вашем проекте) и дублируемый код, соответственно.

Эти две совершенно необходимые утилиты помогут поддерживать ваш код в состоянии, которое соответствует принципам DRY. Как и все вышеописанные инструменты, DCD и CPD могут быть установлены командами:

composer global require 'sebastian/phpcpd=*'
composer global require 'sebastian/phpdcd=*'

Все вместе

Все программы, о которых мы говорили в нашей статье, могут быть установлены следующим набором команд (кроме разве что vfsStream, который вам проще будет запросить в файле composer.json соответствующего проекта):

composer global require 'sebastian/phpcpd=*'
composer global require 'sebastian/phpdcd=*'
composer global require "phpunit/phpunit=4.1.*"
composer global require behat/behat='~3.0.6'
composer global require 'phploc/phploc=*'
composer global require 'phpmd/phpmd=*'
composer global require 'squizlabs/php_codesniffer=*'
composer global require 'sebastian/phpcpd=*'
composer global require 'sebastian/phpdcd=*'

Теперь вы можете использовать любую из этих утилит без необходимости объявлять их вручную в вашем коде.

Заключение

В этой статье мы рассмотрели часть утилит, приведённых на сайте PHP QA Tools, заострив внимание именно на анализе качества, и к тому же обсудили ситуации, в которых эти утилиты будут полезны. В завершение мы создали основу для shell-скрипта, при помощи которого можно установить все эти утилиты глобально, скажем, в среду Vagrant.

Даже если все эти инструменты не найдут применения в вашем текущем проекте, ориентированном на скорость разработки, вы можете попробовать их все в каком-нибудь своём хобби-проекте. Возможно, этот опыт здорово пригодится вам в ближайшем будущем.

Используете ли вы что-нибудь из приведённого нами списка сейчас? Если нет, то почему? Может быть, у вас есть чем дополнить этот список? Дайте нам знать в комментариях, и мы актуализируем эту статью с вашей помощью. Напоминаем: речь идёт только об инструментах обеспечения качества!

РедакцияПеревод статьи «8 Must Have PHP Quality Assurance Tools»