MyTetra Share
Делитесь знаниями!
Тестирование кода с PHPUnit
19.04.2017
17:19
Текстовые метки: PHP, PHPUnit
Раздел: Компьютер - Программирование - Язык PHP - PHPUnit

Создаем первый тест

Итак, давайте рассмотрим следующий класс (файл sqrt_class.php):

<?php

class sqrt_class {

public function sq($x)

{

if($x == 5) {

return TRUE;

}

if($x == 100) {

return FALSE;

}

return sqrt($x);

}

}

?>

Как Вы видите, это очень простой класс, который содержит всего один метод, возвращающий корень квадратный переданного ему параметра $x. Также данный метод проверяет значение данного параметра и если оно равно 5, значит, возвращаем TRUE. Если же значение параметра $x равно 100, значит, вернем FALSE.

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


require_once 'PHPUnit/Autoload.php';


Затем подключаем класс, который нужно протестировать:


require_once 'sqrt_class.php';


Перед созданием класса для тестирования рассмотрим несколько правил создания таких классов:

  • Название класса теста складывается из названия тестируемого класса плюс “Test”.
  • Класс для тестирования практически всегда должен быть наследником класса PHPUnit_Framework_TestCase.
  • Каждый метод теста является публичным методом, название которого начинается с префикса “test”.
  • Внутри метода теста мы используются специальные методы тестирования – assert-методы. Которые и задают способ тестирования.

Теперь создадим класс для тестирования (для лучшего понимания приведу полный код файла test.php):


<?php

require_once 'PHPUnit/Autoload.php';

require_once 'sqrt_class.php';


class sqrt_classTest extends PHPUnit_Framework_TestCase {

public function testSq() {

$my = new sqrt_class();

//метод assertEquals(), который первым обязательным параметром принимает ожидаемое значение, вторым актуальное и проверяет их соответствие.

$this->assertEquals(4, $my->sq(16));

}

}

?>


Как Вы видите, класс для тестирования достаточно простой и содержит всего один метод testSq. Имя данного метода выбрано в соответствии с выше изложенными правилами. То есть мы хотим протестировать метод sq(), значит, имя будет таким же, но с добавлением префикса test. В данном методе, мы создаем объект класса sqrt_class() (класс, метод которого мы хотим протестировать), и сохраняем его в переменной $my. Теперь в зависимости от того, какой тест нужно выполнить, необходимо вызвать специальный assert-метод.

Для первого теста, мы применим метод assertEquals(), который первым параметром принимает ожидаемое значение (то есть то верное значение которое должен возвращать метод), вторым — реальное значение (то есть значение которое действительно возвращается методом). И сравнивает эти два значения. Если они равны – тест пройден успешно. Если же нет — то ошибка.

Теперь как Вы видите, при вызове метода assertEquals(), первым параметром мы передаем значение 4, как ожидаемое. И вторым, передаем вызов метода sq() класса sqrt_class – как реально вычисленное значение. Параметром к методу sq(), передадим значение 16. Значит в результате отработки метода мы должны получить число 4, при этом ожидаемое значение, мы так же передали 4. Значит, тест должен завершиться успешно. Поэтому, давайте выполним тест и проверим.
Для запуска теста, необходимо вернуться в командную строку, перейти в папку с интерпретатором языка php и набрать команду:


phpunit path


где path – это путь к файлу с тестом, в нашем случае это файл test.php. То есть в командной строке выполняем команду:


phpunit z:\home\localhost\www\for_pear\test.php


В результате мы увидим следующее:

Итак, что мы видим. Первое, что бросается в глаза – это приветствие, то есть версия PHPUnit и имя создателя. Далее – точка. Точка – это признак того, что тест выполнен успешно. Затем указана, различная сервисная информация (количество затраченного времени, памяти и т.д). Теперь давайте, изменим ожидаемое значение, с 4 на 2 (то есть первым параметром методу assertEquals() передадим 2) и запустим тест:

Теперь вместо точки мы видим букву F, что означает Fault – ошибка. Ниже можно прочитать в чем именно заключается ошибка теста. То есть тест закончился с ошибкой.

В данном примере, мы рассмотрели передачу двух параметров в метод assertEquals(), но что делать, если нужно протестировать отработку метода, для различных параметров. Не будем же мы для каждого набора параметров, вручную запускать тест? Конечно нет. Для решения данной задачи, необходимо использовать провайдеры данных. Провайдеры данных, содержат в себе массив параметров, которые будут подставлены во время запуска теста. Тем самым, запуская тест мы выполним столько тестов, сколько наборов параметров содержится в провайдере данных.

Провайдер данных это обычный метод, который возвращает массив с набором параметров следующем формате:


public function providerSq ()

{

return array (

array (param1, param2),//параметры для тест 1

array (param1, param2),// параметры для тест 2

array (param1, param2),// параметры для тест 3

array (param1, param2)// параметры для тест 4

);

}


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

  • Метод являющийся провайдером, должен быть назван, как и тестируемый метод, с добавлением приставки provider.
  • Перед тестируемым метод, необходимо указать в специальном комментарии название его провайдера. Следующим образом:


/**

* @dataProvider имя провайдера

*/


Поэтому давайте изменим код класса sqrt_classTest, для использования провайдеров:


class sqrt_classTest extends PHPUnit_Framework_TestCase {

/**

* @dataProvider providerSq

*/

public function testSq($a,$b) {

$my = new sqrt_class();

$this->assertEquals($a, $my->sq($b));

}

public function providerSq ()

{

return array (

array (2, 4),

array (4, 16),

array (5, 5),

array (3, 100)

);

}

}


Теперь, давайте выполним данный тест:

Как Вы видите, сейчас выполнилось четыре теста – для каждого набора параметров. Четвертый тест выполнился с ошибкой. Так как корень квадратный из 100, ни как не может быть равен 3. Наряду с методом assertEquals, есть еще два полезных метода assertTrue() и assertFalse(), которые проверяют, является переданное выражение истинным или ложным соответственно. То есть, метод для тестирования истинности возвращаемого значения:


/**

* @dataProvider providerSq

*/


public function testSq($a,$b) {

$my = new sqrt_class();

$this->assertTrue($my->sq($b));

}


Данный тест успешно выполнится если метод sq(), вернет TRUE. И метод для тестирования того, что тестируемый метод вернет FALSE:

/**

* @dataProvider providerSq

*/

public function testSq($a,$b) {

$my = new sqrt_class();

$this->assertFalse($my->sq($b));

}


Данный тест успешно выполнится если метод sq(), вернет FALSE.


Тестирование массивов

Теперь давайте рассмотрим следующий класс (файл arr_class.php):

<?php

class arr_class {

public function getArr($k)

{

return explode('|',$k);

}

}


Опять же данный класс содержит всего один метод, который параметром принимает строку и разбивает ее в массив, по разделителю “|”. Для тестирования массивов в PHPUnit есть специальные методы. Поэтому давайте рассмотрим код файла test2.php, позволяющий выполнять тестирование массивов:


<?php

require_once 'PHPUnit/Autoload.php';

require_once 'arr_class.php';


class arr_classTest extends PHPUnit_Framework_TestCase {

/**

* @dataProvider providerGetArr

*/

public function testGetArr($key,$str) {

$my = new arr_class();

//$this->assertArrayHasKey($key,$my->getArr($str));

//$this->assertContains($key,$my->getArr($str));

//$this->assertContainsOnly('integer',$my->getArr($str));

//$this->assertCount($key, $my->getArr($str));

}

public function providerGetArr ()

{

return array (

array (3, 'ku|hello|white'),

array (4, 'ku1|hello1|white1'),

array (3, '2|2|2'),

);

}

}


Методы в классе я специально закомментировал, что бы можно было их использовать поочередно:

  • assertArrayHasKey($k, $arr) – проверяет, существует ли ключ $k, в массиве $arr.
  • assertContains($v, $arr) – проверяет существует ли элемент $v в массиве $arr.
  • assertContainsOnly(‘type’, $arr) — проверяет, содержат ли ячейки массива $arr, значения типа данных type.
  • assertCount($count,$arr) – проверяет, соответствует ли число $count, количеству элементов массива $arr.

Запуск теста производим аналогично предыдущим примерам, только не забывайте правильно указывать путь для файла с тестом.


Тестирование исключений

И последнее, что мы рассмотрим – это тестирование исключений. Давайте рассмотрим класс:


<?php

class MyException extends Exception {};

class ex_class {

public function getEx($k)

{

if($k == 10) {

throw new MyException('Wrong var');

}

else return true;

}

}

?>


Класс содержит всего один метод, который генерирует исключение, если переданный ему параметр равен 10. Теперь посмотрите на класс, с помощью которого можно проверить генерацию исключений:


<?php

require "PHPUnit/Autoload.php";

require "ex_class.php";


class ex_classTest extends PHPUnit_Framework_TestCase {

protected $ob;

protected function setUp() {

$this->ob = new ex_class();

}

/**

* @dataProvider providerGetEx

*

*/

public function testGetEx($key) {

$this->setExpectedException("myException");

$this->ob->getEx($key);

}

public function providerGetEx() {

return array(

array(3),

array(1),

array(10),

array(3)

);

}

protected function tearDown() {

$this->ob = NULL;

}

}

?>


Первое, что Вы наверное заметили, это то, что добавилось два метода:
  • setUp() – который выполняется перед тестом. То есть, используя данный метод можно выполнить различные подготовительные действия. К примеру, в нашем случае – создаем объект тестируемого класса и сохраняем в свойство $fixture.
  • tearDown() — который, выполняется после теста. То есть можно удалить лишние данные. В нашем случае удаляем созданный объект тестируемого класса.

Тестировать исключение можно при помощи метода setExpectedException(«myException») или необходимо указать перед тестируемым методом комментарий @expectedException MyException. Тест будет пройден успешно, если метод вернет исключение класса myException.

Вот и все, что я хотел сказать Вам по инструменту PHPUnit. Конечно, мы рассмотрели только основы, так как PHPUnit – это очень мощный и довольно сложный инструмент для тестирования кода. Но если он Вас заинтересовал, то продолжайте его дальнейшее изучение самостоятельно и применяйте изученное на практике.

Документация по PHPUnit содержится на данной странице: http://phpunit.de/manual/current/en/index.html

Всего Вам доброго и удачного кодирования.


 
MyTetra Share v.0.52
Яндекс индекс цитирования