Модульное тестирование (Оценка: +3)

Печать / RSS-лента
Введение
Модульное тестирование это то, чем вы пользуетесь постоянно во время разработки и даже не замечаете этого. В процессе написания кода вы по многу раз запускаете его, чтобы убедится в том, что он работает ожидаемым образом. Так почему бы не автоматизировать этот процесс? Для этих целей применяется "Автоматизированное модульное тестирование" (АМТ) и "Модульные тесты".

АМТ решает следующие важные задачи:
* Позволяет выявить ошибку на раннем этапе разработки, до того, как код уйдет в работу. Своевременное выявление ошибки так же упрощает ее локализацию и исправление
* Позволяет быстро удостоверится в том, что вносимые в систему изменения не поломали старый код
* Облегчает процесс изучения системы новыми разработчиками

Но не следует забывать, что АМТ, как и код системы, требует поддержки и модернизации, что отнимает время у разработчика.

Фреймворк xUnit, часто применяется для создания АМТ во многих языках программирования. Для PHP так же существует его разновидность - PHPUnit. Работу с ним я и опишу в данной статье.

Установка PHPUnit
Для установки фреймворка PHPUnit воспользуйтесь следующей командой (для Linux систем):

wget https://phar.phpunit.de/phpunit.phar
chmod +x phpunit.phar
mv phpunit.phar /usr/local/bin/phpunit


Эта команда загрузит фреймворк, распространяемый в виде PHAR-пакета, предоставит ему права на выполнение и переместит его в соответствующий каталог.

Основы модульного тестирования
АМТ представляет собой множество классов, каждый из которых тестирует конкретную логику системы. Все эти классы должны наследоваться от базового класса PHPUnit_Framework_TestCase и содержать один или более методов, имя которых начинается с test.

Рассмотрим пример создания собственного класса для автоматизированного модульного тестирования. Представим что у нас есть следующий класс, реализующий простой стек:

class MyStack implements Countable{
private $store;

public function __construct(){
$this->store = [];
}

public function push($value){
array_push($this->store, $value);
}

public function pop(){
return array_pop($this->store);
}

public function count(){
return count($this->store);
}
}


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


class MyStackTest extends PHPUnit_Framework_TestCase{
public function testConstruct(){
$stack = new MyStack();

$this->assertEquals(0, count($stack));
}

public function testPush(){
$stack = new MyStack();

$stack->push(5);

$this->assertEquals(1, count($stack));
}

public function testPop(){
$stack = new MyStack();

$stack->push(5);

$this->assertEquals(5, $stack->pop());
$this->assertEquals(0, count($stack));
}
}


Все что вам нужно знать, для понимания этого кода, это метод assertEquals. Он является частью любого модульного теста и проверяет, равен ли первый аргумент второму, и если нет, то тест считается не пройденным.

Для запуска этого теста выполните команду:

phpunit MyStackTest.php


Шаблоны тестирования
Применяя АМТ старайтесь использовать следующие шаблоны:
* Структурируйте тесты - помните, что любой тест всегда состоит из предусловий, вызова и проверки постусловий

public function testPop(){
// Предусловия
$stack = new MyStack();

// Вызов
$stack->push(5);

// Проверка постусловий
$this->assertEquals(5, $stack->pop());
$this->assertEquals(0, count($stack));
}

* Понятные имена для тестов - старайтесь именовать методы теста так, чтобы было понятно, что они проверяют. Так, метод testPop можно было бы переименовать в testPop_shouldSliceCurrentStackValue
* Применение фабрик в тесте - если в одном тесте вы часто создаете один и тот же объект, выделите его состояние в метод-фабрику. Так, код $stack = new MyStack можно было бы обернуть в метод createStack и использовать в тестах следующим образом: $stack = $this->createStack()
* Не проверяйте с помощью тестов внутреннюю логику класса, только постусловия. Другими словами тесту не нужно знать как именно работает класс, достаточно проверить, что при некоторых предусловиях и вызове всегда достигаются данные постусловия
* Не повторяйтесь. Как и при разработке приложения, старайтесь не заниматься "программированием через копипаст" во время написания тестов. Помните, что вы должны их сопровождать, а повторяющийся код сделает сопровождение сложным
* Пишите тесты так, чтобы после их прочтения было понятно, что делает тестируемый класс. Запомните - тесты это особая документация, отвечающая на вопрос: "Что должен и что не должен делать класс"

Послесловие
Я намерено упростил статью, выбросив из нее множество важных деталей, таких как Mock-объекты и тестирование исключений. Если вас заинтересовала тема модульного тестирования, обязательно обратитесь к следующей литературе:
* http://www.ozon.ru/context/detail/id/1501671/
* http://www.ozon.ru/context/detail/id/4127815/
Автор статьи: Артур (08.06.16 / 01:14)
PHPUnit, Тестирование, Unit-test
Рейтинг: +3
Просмотров: 735
Комментарии (9) »