Начинаем работать с Nette Tester
Даже хорошие программисты делают ошибки. Разница между хорошим и плохим программистом в том, что хороший сделает ее только один раз, а в следующий раз обнаружит с помощью автоматизированных тестов.
- “Кто не тестирует, обречен повторять свои ошибки.” (пословица)
- “Как только мы избавляемся от одной ошибки, появляется другая.” (закон Мерфи)
- “Всякий раз, когда у вас возникает желание вывести на экран переменную, лучше напишите тест.” (Мартин Фаулер)
Вы когда-нибудь писали в PHP подобный код?
$obj = new MyClass;
$result = $obj->process($input);
var_dump($result);
То есть вы выводили результат вызова функции только для того, чтобы глазами проверить, возвращает ли она то, что должна? Наверняка вы делаете это много раз в день. Положа руку на сердце: в случае, если все работает правильно, удаляете ли вы этот код? Ожидаете ли вы, что класс в будущем не сломается? Законы Мерфи гарантируют обратное :-)
По сути, вы написали тест. Его нужно лишь немного изменить, чтобы он не требовал визуальной проверки, а проверял себя сам. И если тест не удалить, его можно будет запустить в любое время в будущем и проверить, что все по-прежнему работает, как надо. Со временем таких тестов накопится большое количество, поэтому было бы полезно запускать их автоматически.
И со всем этим вам поможет именно Nette Tester.
Чем уникален Tester?
Написание тестов для Nette Tester уникально тем, что каждый тест — это обычный PHP-скрипт, который можно запустить самостоятельно.
То есть, когда вы пишете тест, вы можете его просто запустить и выяснить, нет ли в нем, например, ошибки программирования. Правильно ли он работает. Если нет, вы можете легко отладить его в своей IDE и найти ошибку. Вы даже можете открыть его в браузере.
И прежде всего — запустив его, вы выполните тест. Вы сразу узнаете,
прошел он или не удался. Как? Давайте покажем. Напишем тривиальный тест
работы с PHP-массивом и сохраним в файл ArrayTest.php
:
<?php
use Tester\Assert;
require __DIR__ . '/vendor/autoload.php'; # загрузка автозагрузчика Composer
Tester\Environment::setup(); # инициализация Nette Tester
$stack = [];
Assert::same(0, count($stack)); # ожидаем, что count() вернет ноль
$stack[] = 'foo';
Assert::same(1, count($stack)); # ожидаем, что count() вернет единицу
Assert::contains('foo', $stack); # проверим, что $stack содержит элемент 'foo'
Как видите, так называемые методы
утверждений вроде Assert::same()
используются для подтверждения
того, что фактическое значение соответствует ожидаемому значению.
Тест написан, и мы можем его запустить из командной строки. Первый запуск выявит возможные синтаксические ошибки, и если вы нигде не допустили опечатки, выведется:
$ php ArrayTest.php
OK
Попробуйте в тесте изменить утверждение на неверное
Assert::contains('XXX', $stack);
и посмотрите, что произойдет при запуске:
$ php ArrayTest.php Failed: ['foo'] should contain 'XXX' in ArrayTest.php(17) Assert::contains('XXX', $stack); FAILURE
Далее о написании продолжаем в главе Написание тестов.
Установка и требования
Минимальная версия PHP, требуемая Tester, — 7.1 (подробнее в таблице поддерживаемые версии PHP). Предпочтительный способ установки — с помощью Composer:
composer require --dev nette/tester
Попробуйте запустить Nette Tester из командной строки (без параметров он просто выведет справку):
vendor/bin/tester
Запуск тестов
По мере роста приложения количество тестов растет вместе с ним. Было бы непрактично запускать тесты по одному. Поэтому Tester располагает пакетным средством запуска тестов, которое мы вызываем из командной строки. В качестве параметра указываем каталог, в котором находятся тесты. Точка означает текущий каталог.
vendor/bin/tester .
Средство запуска тестов просканирует указанный каталог и все
подкаталоги и найдет тесты, то есть файлы *.phpt
и *Test.php
. Он
найдет и наш тест ArrayTest.php
, поскольку он соответствует маске.
Затем он начнет тестирование. Каждый тест запускается как новый процесс PHP, так что он выполняется полностью изолированно от остальных. Он запускает их параллельно в нескольких потоках, и благодаря этому он чрезвычайно быстр. И первыми он запускает тесты, которые при предыдущем запуске не удались, так что вы сразу узнаете, удалось ли вам исправить ошибку.
Во время выполнения тестов Tester непрерывно выводит результаты на терминал в виде символов:
.
– тест пройденs
– тест был пропущен (skipped)F
– тест не удался (failed)
Вывод может выглядеть так:
_____ ___ ___ _____ ___ ___ |_ _/ __)( __/_ _/ __)| _ ) |_| \___ /___) |_| \___ |_|_\ v2.5.2 Note: No php.ini is used. PHP 8.3.2 (cli) | php -n | 8 threads ........s................F......... -- FAILED: greeting.phpt Failed: 'Hello John' should be ... 'Hello Peter' in greeting.phpt(19) Assert::same('Hello Peter', $o->say('John')); FAILURES! (35 tests, 1 failures, 1 skipped, 1.7 seconds)
Было запущено 35 тестов, один не удался, один был пропущен.
Далее продолжаем в главе Запуск тестов.
Режим Watch
Рефакторите код? Или даже разрабатываете по методике TDD (Test Driven Development)? Тогда вам понравится режим watch. Tester в нем отслеживает исходные коды и при изменении сам запускается.
При разработке у вас в углу монитора терминал, где на вас светит зеленая строка состояния, и когда она внезапно меняется на красную, вы знаете, что только что что-то сделали не совсем правильно. Это на самом деле отличная игра, когда вы программируете и стараетесь удержать цвет.
Режим Watch запускается параметром –watch.
Отчеты CodeCoverage
Tester умеет генерировать отчеты с обзором того, сколько исходного кода покрывают тесты. Отчет может быть либо в читаемом человеком формате HTML, либо в Clover XML для дальнейшей машинной обработки.
Посмотрите пример HTML отчета с покрытием кода.
Поддерживаемые версии PHP
версия | совместима с PHP |
---|---|
Tester 2.5 | PHP 8.0 – 8.3 |
Tester 2.4 | PHP 7.2 – 8.2 |
Tester 2.3 | PHP 7.1 – 8.0 |
Tester 2.1 – 2.2 | PHP 7.1 – 7.3 |
Tester 2.0 | PHP 5.6 – 7.3 |
Tester 1.7 | PHP 5.3 – 7.3 + HHVM 3.3+ |
Tester 1.6 | PHP 5.3 – 7.0 + HHVM |
Tester 1.3 – 1.5 | PHP 5.3 – 5.6 + HHVM |
Tester 0.9 – 1.2 | PHP 5.3 – 5.6 |
Действительно для последней версии патча.
Tester до версии 1.7 поддерживал также HHVM 3.3.0 или выше
(через tester -p hhvm
). Поддержка была прекращена с версии Tester 2.0.