Модульные тесты с PHPUnit
Для проекта, который нужно поддерживать или в процессе работы добавлять новые модули и программые решения, просто необходимы тесты. Они существенно сократят количество времени на поиск и устранение возникающих конфликтов и ошибок.
У библиотеки PEAR есть замечательный инструмент - PHPUnit, который занимается unit(модульным)-тестированием. Как раз о нем сегодня и пойдет речь.
Установить PHPUnit можно через консоль (глобально):
$ wget https://phar.phpunit.de/phpunit.phar
$ chmod +x phpunit.phar
$ sudo mv phpunit.phar /usr/local/bin/phpunit
Или же через composer (только для проекта). Для этого в файле composer.json добавляем в зависимости библиотеку:
{
"name": "project name",
"require": {
"phpunit/phpunit": "5.5.*"
}
}
Сохраняем файл и выполняем команду composer install.
Стоит заметить, что если мы установим PHPUnit глобально, то запускать тесты будем так: phpunit, а если через composer, то так: ./vendor/bin/phpunit.
После установки создаем файл phpunit.xml:
<?xml version="1.0" encoding="UTF-8"?>
<phpunit backupGlobals="false"
backupStaticAttributes="false"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="false"
stopOnFailure="false"
colors="true">
<testsuites>
<testsuite name="UnitTest">
<directory suffix="Test.php">tests/unit/</directory>
</testsuite>
</testsuites>
</phpunit>
В конфигурации мы указываем путь к нашим файлам с тестами (tests/unit/), а также, по желанию, префикс для этих файлов (Test.php). Опции, такие как colors="true" обсуждать не будем, поскольку по названию и так можно догадаться, что они настраивают. Но, при желании, всегда можно почитать о них на официальном сайте.
Ну что ж, теперь давайте приступим к тестированию. А начнем, например, с создания тестов для модели продукта (tests/unit/ProductTest.php):
class ProductTest extends PHPUnit_Framework_TestCase
{
protected $product;
protected function setUp()
{
$this->product = new Product();
}
protected function tearDown()
{
$this->product = null;
}
/**
* Проверка на обязательные поля.
*/
public function testRequiredFields()
{
$this->product->name = '';
$this->product->price = '';
$this->assertFalse($this->product->save());
$this->product->name = 'имя продукта';
$this->product->price = 5000;
$this->assertTrue($this->product->save());
}
/**
* Проверка на получение категории.
*/
public function testGetCategory()
{
$category = $this->product->getCategory();
$this->assertInstanceOf(get_class($category), new Category);
$this->assertEquals($category->id, 1);
}
}
Метод setUp() вызывается перед каждым тестом, tearDown() после каждого теста, а вот testRequiredFields() и testGetCategory() это как раз наши функции тестирования методов объекта Product. Т.е. из примера выше последовательность вызовов будет такая: setUp(), testRequiredFields(), tearDown(), setUp(), testGetCategory(), tearDown().
Такие методы как $this->assertTrue() или $this->assertEquals() - это собственно и есть функции сравнения объектов, которые предоставляет PHPUnit. Со всеми методами сравнения можно ознакомится на официальном сайте PHPUnit.
Ну а теперь давайте запустим наши тесты:
$ phpunit # или `./vendor/bin/phpunit` в зависимости от того как установлен пакет
И посмотрим на результат:
PHPUnit 5.5.0 by Sebastian Bergmann and contributors.
.. 2 / 2 (100%)
Time: 72 ms, Memory: 7.75MB
OK (2 tests, 4 assertions)
Вот таким простым способом можно покрыть тестами весь проект и не опасаться, что при очередном обновлении неожиданно появятся ошибки, которые нужно будет срочно исправлять.