
В предыдущей статье я описал способы установки PHPUnit.
Создание теста заключается в создании отдельного файла с классом, который будет отвечать за тестирование определенного класса приложения.
Имя тестирующего класса образуется добавлением приставки Test к имени тестируемого класса. Например, вы тестируете класс User, значит имя тестирующего — UserTest. Название файла с классом должно совпадать с названием класса + расширение .php т.е. UserTest.php
Имена тестирующих методов всегда должны начинаться с “test” (например testNewUserReturnTrue). Методы должны быть публичными.
Тестирующие методы не принимают параметров (кроме провайдеров данных). Вы должны писать тестирующие методы максимально независимыми и самодостаточными.
В примерах, часто, подключается тестируемый файл таким образом:
require_once dirname(__FILE__).'/../User.php';На самом деле в реальных проектах, использующих пространства имен, подключение должно осуществляться автоматически, обычно с помощью автозагрузчика Composer. Конечно для этого нужно следовать стандартам psr при подключении классов проекта.
Самый простой пример.
Файл app\Model.php:
<?php namespace app; class Model { public function check() { // return true; } }
Файл test\ModelTest.php:
<?php namespace tests; use PHPUnit\Framework\TestCase; use app\Model; class ModelTest extends TestCase { public function testCheckTrue(){ $model = new Model(); $this->assertTrue($model->check()); } }В данном примере мы тестируем метод check() класса Model на то, что в результате своей работы он вернет true.
В строке
$this->assertTrue($model->check());
используется метод фреймворка для тестирования PHPUnit assertTrue(), который ожидает от вызова метода check() возвращаемое значение true. Если ожидание подтверждается, то тест будет пройден успешно.
В PHPUnit множество таких проверочных методов и все они начинаются с assert*. Перечислю основные из них:
AssertTrue/AssertFalse - Проверка переданных значений на равенство true/false
AssertEquals - Проверка переданных значений на равенство
AssertGreaterThan - Сравнивает две переменные (есть так же LessThan, GreaterThanOrEqual, and LessThanOrEqual)
AssertContains - Содержит ли переданная переменная заданное значение
assertInternalType (было AssertType) - Проверка типа переменной (string, integer…)
assertInstanceOf - Проверка типа переменной (объекты)
AssertNull - Проверка на равенство null
AssertFileExists - Проверка существования файла
AssertRegExp - Проверка по регулярному выражению
остальные методы и примеры использования можно посмотреть тут в левой колонке, в графе A. Assertions.
Запуск тестов.
Тесты запускаются в командной строке.- из папки текущего проекта:
phpunit testsзапуск отдельного файла тестов:
phpunit tests\ModelTestили
phpunit tests\ModelTest.php
- из любого места (указываем полный путь):
phpunit W:\domains\test.loc\tests\ModelTest.php
Если PHPUnit устанавливали с помощью Composer, то по-умолчанию запускать так:
vendor/bin/phpunit testsНо лучше создать файл phpunit.bat и phpunit.xml чтобы запускать тестирование одной командой:
phpunit
Про создание файла phpunit.bat можно прочитать в предыдущей статье, а phpunit.xml представляет из себя конфигурационный файл, откуда PHPUnit сможет брать данные, чтобы не приходилось их прописывать в командной строке. Создадим данный файл в корне проекта и пропишем там:
<?xml version="1.0" encoding="UTF-8"?> <phpunit colors="true"> <testsuites> <testsuite> <directory>tests/</directory> </testsuite> </testsuites> </phpunit>тут мы указали, что тесты хранятся в папке tests, а заодно подсветили вывод результатов выполнения тестов в командной строке.
Данный файл можно так же создать автоматически командой
phpunit --generate-configurationБудет предложено выбрать соответствующие каталоги или нажать «Enter» для значений по-умолчанию.
Таки образом, настроив PHPUnit вы сможете запускать тесты простой командой: phpunit
При выполнении тестирования, для каждого тестового прогона, РНРUnit framework, в командной строке выводит один символ, указывающий на прогресс выполнения тестирование PHP кода:
. Печатается, когда тест завершается успешно.
F Печатается, когда утверждение терпит неудачу при выполнении тестового метода.
E Печатается, когда возникают ошибки при выполнении тестового метода.
R Печатается, когда тест был отмечен как рискованный (см в следующих статьях).
S Печатается, когда тест был пропущен (см в следующих статьях).
I Печатается, когда тест помечается как неполный или еще не реализован (см в следующих статьях).
При выполнении нашего примера, в консоли должно отобразиться:

Пример 2.
В данном примере я не использую автозагрузчик классов. Будем считать, что РНРUnit мы установили вручную.
Файл User.php:
<?php class User { public function getPassword(array $user) { if(isset($user['login'])){ $user['password'] = uniqid($user['login']); return $user; } return false; } }Метод getPassword() получает массив текущего пользователя ($user) и на основе его логина создает временный пароль дополняя массив $user новым элементом - 'password'.
Тест проверяющий наличие элемента с ключем 'password' в массиве $user, который должен вернуть метод getPassword() после выполнения.
Файл tests\UserTest.php:
<?php require_once dirname(__FILE__).'/../User.php'; use PHPUnit\Framework\TestCase; class UserTest extends TestCase { public function testGetPassword() { $obj = new User(); $user['login'] = 'login'; $this->assertArrayHasKey('password', $obj->getPassword($user)); } }для тестирования передаем методу getPassword() массив $user с необходимым элементом 'login' и рассчитываем что в возвращаемом им результате (массиве) будет элемент с ключем 'password'.
РНРUnit использует несколько вспомогательных методов. В своих примерах я создавал объект тестируемого класса непосредственно в тестируемом методе, например:
$obj = new User();Но в классе теста, как правило, есть несколько тестовых методов. Таким образом неправильно было бы дублировать код, а именно создавать объект тестируемого класса в каждом методе. В данном случае удобно использовать метод setUp(), который выполняется перед каждым тестирующим методом. Объект нужного класса создаем в нем, например:
class MyClassTest{ protected $user; protected function setUp() { $this->user = new User(); } ...дальше обращаемся к методу объекту из любого тестирующего метода:
$this->user;Есть так же метод tearDown(), который выполняется уже после выполнения тестирующего метода.
Нужно учесть, что при использовании метода setUp(), объект будет создаваться перед каждым тестом, что нужно не всегда. Это может понадобиться если тесты изменяют свойства объекта, а он нужен в первозданном виде. В противном случае стоит использовать статический метод setUpBeforeClass() для разового создания и сохранения объекта в статичном свойстве, например:
static $user; //объект нового пользователя public static function setUpBeforeClass() { self::$user = new User(); }Метод setUpBeforeClass() выполняется только раз перед созданием объекта тестирующего класса.
Получить объект в нужном методе:
static::$userТак же существует статический метод tearDownAfterClass() который выполнится после завершения работы всех тестов класса.
Данная статья является одной из серии статей про фреймворк для тестирования PHPUnit. Читайте так же:
- Установка PHPUnit.
- Основы PHPUnit - 2 часть.
- PHPUnit - тестирование исключений, анализ покрытия кода тестами.
- PHPUnit - создание и использование имитирующих объектов (mock), заглушек.