Предисловие переводчика
Эта статья продолжает серию переводов официальной документации по PHPUnit на русский язык.
Часть 1, Часть 2
Пример 4.1 демонстрирует как с помощью PHPUnit можно выполнить тестирование операций с массивами PHP. В этом примере показаны базовые соглашения и шаги, свойственные тестам PHPUnit:
«Пишите тест в независимости от того хотите ли Вы вывести значение через функцию
выражение отладки.» Martin Fowler
«Unit-тесты обычно пишутся, чтобы помочь разработчику найти и исправить ошибки, выполнить рефакторинг кода и облегчить документирование модулей.
Чтобы достичь эти цели, тесты в идеале должны покрывать все возможные пути в программе.
Обычно один тест покрывает один специфический путь в одной функции или методе.
Однако тестовый метод не обязательно может быть инкапсулированной, независимой сущностью.
Часто существуют не очевидные зависимости между тестами, скрытые в реализации тестовых сценариев».
Adrian Kuhn et. al.
PHPUnit поддерживает декларирование явных зависимостей между тестами.
Такие зависимости не определяют в какой последовательности тесты должны выполняться,
однако они позволяют возвращать экземпляр тестового окружения (fixture) и передавать его в другой тест; источник (producer) передает приемнику(consumer).
Пример 4.2: Использование аннотации
Второй тест,
Мы хотим, чтобы наше внимание фокусировалось на важных сообщениях о провале тестов, это позволит максимально быстро находить дефекты.
По этой причине PHPUnit пропускает выполнение зависимых тестов, если Источник (основной тест) закончил работу с ошибкой. Улучшение обнаружения дефектов достигается за счет использования зависимостей между тестами, как показано в Примере 4.3.
Пример 4.3: Использование зависимостей между тестами
У теста может быть несколько аннотаций
PHPUnit не изменяет последовательность, в которой запускаются тесты,
Вы должны быть уверены, что зависимости будут выполнены до того как тест запустится.
Тестовый метод может работать с произвольными аргументами.
Аргументы передаются с помощью метода источника данных (
Метод источника данных должен быть определен с помощью аннотации
Метод источника данных должен быть
Для каждого массива, который является частью коллекции, будет вызван тестовый метод. В качестве аргумента методу будет передан массив значений.
Пример 4.4: Использование источника данных
Если тестовому методу одновременно передаются параметры от источника данных (
Пример 4.5 демонстрирует как использовать аннотацию
исключений, которые выбрасываются внутри тестового кода.
Пример 4.5: Использование аннотации @expectedException
Метод
Пример 4.6: Ожидается, что тестовый метод выбросит исключение
В таблице 4.1 приведены методы для тестирования исключений.
Таблица 4.1 (текстовый вариант). Методы для тестирования исключений
— Установка имени ожидаемого исключения —
— Получение имени ожидаемого исключения.
Для тестирования исключений Вы можете использовать подход, показанный в Примере 4.7.
Пример 4.7: Альтернативный подход к тестированию исключений
Ожидается, что код, показанный в Примере 4.7 выбросит исключение. Если это не произойдет, то будет вызван метод
(см. Таблицу 22.2), который прервет выполнение теста и просигнализирует об ошибке.
Если исключение будет сгенерированно, то сработает блок
По умолчанию, ошибки, предупреждения и уведомления PHP, которые появляются во время тестирования, PHPUnit преобразует в исключения. Используя эту особенность, Вы можете, например, настроить механизм ожидания появления подобного исключения в тесте, см. Пример 4.8.
Пример 4.8: Применение @expectedException для ожидяния ошибки PHP
представляют PHP уведомления и предупреждения.
Продолжение:
Часть 4
Эта статья продолжает серию переводов официальной документации по PHPUnit на русский язык.
Часть 1, Часть 2
Пример 4.1 демонстрирует как с помощью PHPUnit можно выполнить тестирование операций с массивами PHP. В этом примере показаны базовые соглашения и шаги, свойственные тестам PHPUnit:
- Наименование тестирующего класса образуется путем добавления постфикса
Test
к наименованию тестируемого класса. Например тестируемый класс называетсяClass
, тестирующий —ClassTest
. ClassTest
наследуется (в большинстве случаев) от PHPUnit_Framework_TestCase.- Наименования тестирующих методов образуются путем добавления приставки
test
к наименованиям тестируемых методов. - Внутри тестовых методов утверждения задаются специальными функциями
assertEquals()
(смотрите раздел PHPUnit_Framework_Assert).assertEquals()
задает соответствие реально полученного значения и ожидаемого.
<?php<br>
require_once 'PHPUnit/Framework.php';<br>
<br>
class StackTest extends PHPUnit_Framework_TestCase<br>
{<br>
public function testPushAndPop()<br>
{<br>
$stack = array();<br>
$this->assertEquals(0, count($stack));<br>
<br> array_push($stack, 'foo');<br>
$this->assertEquals('foo', $stack[count($stack)-1]);<br>
$this->assertEquals(1, count($stack));<br>
<br> $this->assertEquals('foo', array_pop($stack));<br>
$this->assertEquals(0, count($stack));<br>
}<br>
}<br>
?><br>
<br>
* This source code was highlighted with Source Code Highlighter.
«Пишите тест в независимости от того хотите ли Вы вывести значение через функцию
print
или выражение отладки.» Martin Fowler
Зависимости тестов
«Unit-тесты обычно пишутся, чтобы помочь разработчику найти и исправить ошибки, выполнить рефакторинг кода и облегчить документирование модулей.
Чтобы достичь эти цели, тесты в идеале должны покрывать все возможные пути в программе.
Обычно один тест покрывает один специфический путь в одной функции или методе.
Однако тестовый метод не обязательно может быть инкапсулированной, независимой сущностью.
Часто существуют не очевидные зависимости между тестами, скрытые в реализации тестовых сценариев».
Adrian Kuhn et. al.
PHPUnit поддерживает декларирование явных зависимостей между тестами.
Такие зависимости не определяют в какой последовательности тесты должны выполняться,
однако они позволяют возвращать экземпляр тестового окружения (fixture) и передавать его в другой тест; источник (producer) передает приемнику(consumer).
- Источник — это тестовый метод, который возвращает значения, от которых зависят другие методы модуля.
- Приемник — это тестовый метод, который зависит от одного или более источников и их возвращаемых значений.
@depends
для описания зависимостей между тестами.Пример 4.2: Использование аннотации
@depends
для описания зависимостейВ этом примере первый тест,<?php<br>
class StackTest extends PHPUnit_Framework_TestCase<br>
{<br>
public function testEmpty()<br>
{<br>
$stack = array();<br>
$this->assertTrue(empty($stack));<br>
<br>
return $stack;<br>
}<br>
<br>
/**<br>
* @depends testEmpty<br>
*/<br>
public function testPush(array $stack)<br>
{<br>
array_push($stack, 'foo');<br>
$this->assertEquals('foo', $stack[count($stack)-1]);<br>
$this->assertFalse(empty($stack));<br>
<br>
return $stack;<br>
}<br>
<br>
/**<br>
* @depends testPush<br>
*/<br>
public function testPop(array $stack)<br>
{<br>
$this->assertEquals('foo', array_pop($stack));<br>
$this->assertTrue(empty($stack));<br>
}<br>
}<br>
?><br>
<br>
* This source code was highlighted with Source Code Highlighter.
testEmpty()
, создает пустой массив и задает утверждение, что массив пустой. После этого тест возвращает окружение (fixture) в качестве результата. Второй тест,
testPush()
, зависит от testEmpty()
и получает результат работы testEmpty()
в качестве аргумента. И наконец, testPop()
зависит от testPush()
. Мы хотим, чтобы наше внимание фокусировалось на важных сообщениях о провале тестов, это позволит максимально быстро находить дефекты.
По этой причине PHPUnit пропускает выполнение зависимых тестов, если Источник (основной тест) закончил работу с ошибкой. Улучшение обнаружения дефектов достигается за счет использования зависимостей между тестами, как показано в Примере 4.3.
Пример 4.3: Использование зависимостей между тестами
<?php<br>
class DependencyFailureTest extends PHPUnit_Framework_TestCase<br>
{<br>
public function testOne()<br>
{<br>
$this->assertTrue(FALSE);<br>
}<br>
<br>
/**<br>
* @depends testOne<br> */<br>
public function testTwo()<br> {<br>
}<br>}<br>?><br>
<br>
* This source code was highlighted with Source Code Highlighter.
phpunit --verbose DependencyFailureTest PHPUnit 3.4.2 by Sebastian Bergmann. DependencyFailureTest FS Time: 0 seconds There was 1 failure: 1) testOne(DependencyFailureTest) Failed asserting that <boolean:false> is true. /home/sb/DependencyFailureTest.php:6 There was 1 skipped test: 1) testTwo(DependencyFailureTest) This test depends on "DependencyFailureTest::testOne" to pass. FAILURES! Tests: 2, Assertions: 1, Failures: 1, Skipped: 1.
У теста может быть несколько аннотаций
@depends
.PHPUnit не изменяет последовательность, в которой запускаются тесты,
Вы должны быть уверены, что зависимости будут выполнены до того как тест запустится.
Источники данных (Data Providers)
Тестовый метод может работать с произвольными аргументами.
Аргументы передаются с помощью метода источника данных (
provider()
, см. Пример 4.4).Метод источника данных должен быть определен с помощью аннотации
@dataProvider
.Метод источника данных должен быть
public
и должен возвращать массив массивов или объект, поддерживающий интерфейс Iterator
, который на каждой итерации возвращает массив.Для каждого массива, который является частью коллекции, будет вызван тестовый метод. В качестве аргумента методу будет передан массив значений.
Пример 4.4: Использование источника данных
<?php<br>
class DataTest extends PHPUnit_Framework_TestCase<br>
{<br>
/**<br>
* @dataProvider provider<br>
*/<br>
public function testAdd($a, $b, $c)<br>
{<br>
$this->assertEquals($c, $a + $b);<br>
}<br>
<br>
public function provider()<br>
{<br>
return array(<br>
array(0, 0, 0),<br>
array(0, 1, 1),<br>
array(1, 0, 1),<br>
array(1, 1, 3)<br>
);<br>
}<br>
}<br>
?><br>
<br>
* This source code was highlighted with Source Code Highlighter.
phpunit DataTest PHPUnit 3.4.2 by Sebastian Bergmann. ...F Time: 0 seconds There was 1 failure: 1) testAdd(DataTest) with data (1, 1, 3) Failed asserting that <integer:2> matches expected value <integer:3>. /home/sb/DataTest.php:21 FAILURES! Tests: 4, Assertions: 4, Failures: 1.
Примечание
Если тестовому методу одновременно передаются параметры от источника данных (
@dataProvider
) и одного или нескольких тестов, которые определены как зависимые (@depends
), то в первую очередь используется источник данных и только потом другие тесты.Тестирование исключений
Пример 4.5 демонстрирует как использовать аннотацию
@expectedException
для тестированияисключений, которые выбрасываются внутри тестового кода.
Пример 4.5: Использование аннотации @expectedException
<?php<br>
require_once 'PHPUnit/Framework.php';<br>
<br>
class ExceptionTest extends PHPUnit_Framework_TestCase<br>
{<br>
/**<br>
* @expectedException InvalidArgumentException<br>
*/<br>
public function testException()<br>
{<br>
}<br>
}<br>
?><br>
<br>
* This source code was highlighted with Source Code Highlighter.
phpunit ExceptionTest PHPUnit 3.4.2 by Sebastian Bergmann. F Time: 0 seconds There was 1 failure: 1) testException(ExceptionTest) Expected exception InvalidArgumentException FAILURES! Tests: 1, Assertions: 1, Failures: 1.
Метод
setExpectedException()
— это еще один способ указать, что в тестовом методе выбрасывается исключение, см. Пример 4.6.Пример 4.6: Ожидается, что тестовый метод выбросит исключение
<?php<br>
require_once 'PHPUnit/Framework.php';<br>
<br>
class ExceptionTest extends PHPUnit_Framework_TestCase<br>
{<br>
public function testException()<br>
{<br>
$this->setExpectedException('InvalidArgumentException');<br>
}<br>
}<br>
?><br>
<br>
* This source code was highlighted with Source Code Highlighter.
phpunit ExceptionTest PHPUnit 3.4.2 by Sebastian Bergmann. F Time: 0 seconds There was 1 failure: 1) testException(ExceptionTest) Expected exception InvalidArgumentException FAILURES! Tests: 1, Assertions: 1, Failures: 1.
В таблице 4.1 приведены методы для тестирования исключений.
Таблица 4.1 (текстовый вариант). Методы для тестирования исключений
void setExpectedException(string $exceptionName)
— Установка имени ожидаемого исключения —
$exceptionName
.String getExpectedException()
— Получение имени ожидаемого исключения.
Для тестирования исключений Вы можете использовать подход, показанный в Примере 4.7.
Пример 4.7: Альтернативный подход к тестированию исключений
<?php<br>
require_once 'PHPUnit/Framework.php';<br>
<br>
class ExceptionTest extends PHPUnit_Framework_TestCase {<br>
public function testException() {<br>
try {<br>
// ... Code that is expected to raise an exception ...<br>
}<br>
<br>
catch (InvalidArgumentException $expected) {<br>
return;<br>
}<br>
<br>
$this->fail('An expected exception has not been raised.');<br>
}<br>
}<br>
?><br>
<br>
* This source code was highlighted with Source Code Highlighter.
Ожидается, что код, показанный в Примере 4.7 выбросит исключение. Если это не произойдет, то будет вызван метод
fail()
, (см. (см. Таблицу 22.2), который прервет выполнение теста и просигнализирует об ошибке.
Если исключение будет сгенерированно, то сработает блок
catch
и тест завершится успешно.Тестирование ошибок PHP
По умолчанию, ошибки, предупреждения и уведомления PHP, которые появляются во время тестирования, PHPUnit преобразует в исключения. Используя эту особенность, Вы можете, например, настроить механизм ожидания появления подобного исключения в тесте, см. Пример 4.8.
Пример 4.8: Применение @expectedException для ожидяния ошибки PHP
<?php<br>
class ExpectedErrorTest extends PHPUnit_Framework_TestCase<br>
{<br>
/**<br>
* @expectedException PHPUnit_Framework_Error<br>
*/<br>
public function testFailingInclude()<br>
{<br>
include 'not_existing_file.php';<br>
}<br>
}<br>
?><br>
<br>
* This source code was highlighted with Source Code Highlighter.
phpunit ExpectedErrorTest PHPUnit 3.4.2 by Sebastian Bergmann. . Time: 0 seconds OK (1 test, 1 assertion)
PHPUnit_Framework_Error_Notice
и PHPUnit_Framework_Error_Warning
представляют PHP уведомления и предупреждения.
Продолжение:
Часть 4