Статьи по php

Как тестировать приложения PHP с помощью PHPUnit

В этом руководстве мы вернемся к PHP и на этот раз рассмотрим, как создавать модульные тесты. Это поможет нам создавать более надежные и менее подверженные ошибкам приложения 💪.

Но прежде всего, и для тех, кто не имеет четкого представления о….

Что такое модульные тесты?

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

Создадим проект, чтобы посмотреть на все более наглядно.

Создаем структуру нашего проекта. Сначала мы создадим две папки в корневом каталоге, одну назовем app, а другую – tests. Далее создадим файл composer.json со следующим содержимым:

{ "name": "alber/unit-test-php", "description": "Руководство по настройке проекта с помощью PHPUnit", "type": "project", "license": "MIT", "authors": [ { "name": "Ivan", "email": "ivan@gmail.com" } ], "minimum-stability": "stable", "require": { }, "autoload": { "psr-4": { "App\\": "app/" } } }
Code language: JSON / JSON with Comments (json)

После этого мы запускаем команду composer dump для создания autoload:

composer dump

Далее мы установим PHPUnit. Это будет библиотека, которую мы будем использовать для создания наших тестов.

composer require --dev phpunit/phpunit
Code language: JavaScript (javascript)

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

<?xml version="1.0" encoding="UTF-8"?> <phpunit bootstrap="vendor/autoload.php" colors="true"> <testsuite name="Test directory"> <directory>tests</directory> </testsuite> </phpunit>
Code language: HTML, XML (xml)

Фактически, мы передаем в атрибуте bootstrap файл загрузки класса, а в testsuite – каталог, в котором мы будем сохранять тесты, который в нашем случае будет находиться в папке tests.

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

<?php namespace App\Classes; class Calc { public function sum(int $num1, int $num2) { return $num1 + $num2; } }
Code language: HTML, XML (xml)

Как вы можете видеть, это очень простой код. В нем просто есть функция, которая берет два числа и вычисляет сумму.

После того как это сделано, пришло время создать наш первый тест. Для этого перейдем в папку tests и в ней создадим файл CalcTest.php. Очень важно, чтобы имя файла имело формат CamelCase и заканчивалось Test.php. Это способ, который использует PHPUnit для определения того, когда это тест, а когда нет. Если он не имеет такого формата, тест выполнен не будет, поэтому не забывайте об этой детали.

После создания файла мы открываем его и добавляем следующий код:

После создания файла мы открываем его и добавляем следующий код:

<?php use PHPUnit\Framework\TestCase; use App\Classes\Calc; class CalcTest extends TestCase { public function test_sum() { $calc = new Calc(); $result = $calc->sum(1, 2); $this->assertEquals(3, $result); } }
Code language: HTML, XML (xml)

Как вы видите, первое, что мы делаем, это добавляем библиотеку PHPUnit и наш класс Calc.

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

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

Внутри test_sum мы создаем экземпляр класса Calc и выполняем метод sum, который возвращает результат. Для проверки теста мы будем использовать метод assertEquals, который является методом класса TestCase и в переводе означает что-то вроде “определить, равны ли они”. В этом методе в качестве первого параметра мы передаем результат, который ожидаем получить, а во втором – результат, который мы получили, чтобы подтвердить, что все в порядке.

Сейчас, когда мы создали наш тест, пришло время проверить его. Для этого переходим в наш корневой каталог и запускаем следующую команду:

php vendor/phpunit/phpunit/phpunit

Если все прошло успешно, мы должны получить сообщение о том, что все наши тесты успешно пройдены.

Кроме assertEquals, у нас есть еще много типов подтверждений, как вы можете видеть в этом списке. Например, если мы хотим подтвердить, что возвращаемый результат является целым числом, мы можем использовать AssertIsInt:

<?php use PHPUnit\Framework\TestCase; use App\Classes\Calc; class CalcTest extends TestCase { public function test_sum() { $calc = new Calc(); $result = $calc->sum(1, 2); $this->assertEquals(3, $result); $this->assertIsInt($result); } }
Code language: HTML, XML (xml)

setUp() и tearDown()

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

Чтобы увидеть их в действии, вернемся к классу Calc и добавим новый метод так, чтобы теперь он выглядел следующим образом:

<?php namespace App\Classes; class Calc { public function sum(int $num1, int $num2) { return $num1 + $num2; } public function res(int $num1, int $num2) { return $num1 - $num2; } }
Code language: HTML, XML (xml)

Затем мы возвращаемся к нашему тесту и изменяем его, чтобы добавить новый тест, а также посмотреть, как применить метод setUp():

<?php use PHPUnit\Framework\TestCase; use App\Classes\Calc; class CalcTest extends TestCase { public $calc = null; public function setUp(): void { $this->calc = new Calc(); } public function test_sum() { $result = $this->calc->sum(1, 2); $this->assertEquals(3, $result); $this->assertIsInt($result); } public function test_res() { $result = $this->calc->res(2, 1); $this->assertEquals(1, $result); $this->assertIsInt($result); } }
Code language: HTML, XML (xml)

Как вы видите, мы добавили метод setUp, который будет создавать экземпляр класса каждый раз, когда выполняется тест. Таким образом, наши тесты будут выглядеть чище и понятнее.

Заключение

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

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

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