Модульное тестирование (Unit tests) с помощью PHPUnit

Зачем нужны тесты и какие виды тестов должен писать разработчик вы можете без проблем узнать здесь.

Адриан Кун(Adrian Kuhn) и иные:

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

Для достижения данных преимуществ модульные тесты в идеале должны охватывать все возможные пути исполнения программы. Один модульный тест обычно покрывает один конкретный путь в одной возможности или способе. Однако тестовые способы необязательно должны быть инкапсулированными и независимыми.

Часто существуют неявные зависимости между тестовыми способами, скрытые в сценарии реализации теста.

Установка PHPUnit и написание первый тест

Для начала необходимо установить версию php7.2+ и composer. Далее в проекте устанавливаем phpunit:

composer require --dev phpunit/phpunit

Создаем пример для теста Duck.php:

class Duck {public function say(): string {return 'krya-krya';}}

Создаем папку tests и добавляем туда тестируем класс DuckTest.php(по умолчанию PHPUnit смотрит на все файлы в которые заканчиваются на Test.php).

require_once __DIR__. '/../Duck.php';class Krya_Test extends \PHPUnit\Framework\TestCase {public function test_say() {$krya = new Duck();$this->assertSame( 'krya-krya', $krya->say());}}

И запускаем тесты:

vendor/bin/phpunit tests/

Если вы увидели такое сообщение, то все сделано верно.

PHPUnit 9.0.1 by Sebastian Bergmann and contributors.. 1 / 1(100%)Time: 42 ms, Memory: 4.00 MBOK(1 test, 1 assertion)

Базовые вещи, которые необходимо знать:

Модульное тестирование(Unit tests) при помощи PHPUnit

Фикстуры(Fixture)

Фиксутра — параметр окружения и возврат его в исходное состояние. Звучит страшно, но фактически это просто способы, которые могут изменить окружение для теста. В классе \PHPUnit\Framework\TestCase для этого есть способы:

  • setUp выполняются перед каждым тестом тестового класса;
  • tearDown выполняются после каждого теста тестового класса;
  • setUpBeforeClass — выполняется перед первым тестом в тестовом классе;
  • tearDownAfterClass — выполняется после запуска последнего теста тестового класса.

Пример:

class FixtureTest extends \PHPUnit\Framework\TestCase {private $counter;protected function setUp(): void {$this->counter = 0;parent::setUp();}public function test_fixture_1() {$this->counter++;$this->assertSame( 1, $this->counter);}public function test_fixture_2() {$this->assertSame( 0, $this->counter);}}

Получается в каждом тестируемом способе свойство counter будет равно 0.

Утверждение(Asserts)

Утверждения — это способы класса TestCase, которые помогают проверить тест. Все данные способы начинаются с assert(assertTrue, assertSame, assertClassHasAttribute и т.д.). После выполнения тестов будет показано кол-во выполненных тестов и кол-во выполненных утверждений. В случае неверного утверждения тест считается проваленным.

Тестовые двойники(Заглушки, Stubs, Mocks)

Stub — объект, который заменяет реальный объект. К примеру у нас есть класс Duck в конструктор которого должен попасть объект Headdress:

use PHPUnit\Framework\TestCase;class StubTest extends TestCase {public function testStub() {$headdress = $this->createMock(Headdress::class);$duck = new Duck( $headdress);$this->assertSame('foo', $duck->quack());}}

Mock — отличается от стаба тем, что ещё описывает какое-то поведение и его изменение влияет на выполнение теста.

При тестировании одного класса в различных его способах один и тот же внешний объект может быть как моком, так и стабом.

use PHPUnit\Framework\TestCase;class MockTest extends TestCase {public function testMock() { $headdress = $this->createMock(Headdress::class);$headdress->expects( 'back');$duck = new Duck( $headdress);$this->assertTrue( $duck->run());}}

В нашем примере мы ещё описали, что ожидаем, что Duck при вызове способ run вызовет внутри себя способ back объекта Headdress.

Параметр окружения для всех тестов(Bootstrap)

Для параметра окружения для всех тестов можно создать файл bootstrap.php и объявить там необходимые вещи. Например в этом файле мы можем подключить библиотеки необходимые для тестирования, настроить глобальные и супер-переменные, объявить константы и т.д.

Пример bootstrap.php файла:

define( 'PLUGIN_PATH', __DIR__ '/../');require_once PLUGIN_PATH. '/vendor/autoload.php';

Конфигурационный XML-файл

Мы можем изменить выполнение команд при помощи конфигурационного XML-файла, в котором можно настроить стандартные параметра phpunit, указать папку с тестами, путь к бутстап файлу, изменить фильтры и иное.

Пример XML-файла:

<phpunit bootstrap="./bootstrap.php" colors="true"> <testsuites> <testsuite name="Config-example-for-tests">    <directory suffix=".php">./tests/</directory>        </testsuite>    </testsuites>    <filter>        <whitelist>            <directory suffix=".php">../../</directory>            <exclude>                <directory>../../src</directory>                <directory>../../tests</directory>                <directory>../../vendor</directory>            </exclude>        </whitelist>    </filter></phpunit>

Атрибутами или вложенными тегами к <phpunit> могут быть любые команды, которые есть в phpunit. В нашем случае

vendor/bin/phpunit /tests/ --bootsrap /tests/bootsrap.php --colors --test-suffix=".php"...

Меняется на:

vendor/bin/phpunit --configuration phpunit.xml

Покрытие тестами(Tests coverage)

При помощи этого инструмента без проблем понять насколько качественно написаны тесты, сколько файлов покрыты тестами и какие строки в них покрыты. Данный инструмент сильно помогает отслеживать качество тестов.

Надо к php-cli подключить xdebug иначе coverage будет недоступен и вы получите уведомление об отсутствии модуля для тестирования.

Чтобы его использовать достаточно дописать к phpunit —coverage-{type} атрибут. К примеру удобно использовать HTML-формат покрытия:

vendor/bin/phpunit --configuration phpunit.xml --coverage-html coverage

После этого в проекте создается папка coverage и мы можем открыть файл index.html и просмотреть подробную информацию о каждом файле тестирования.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *