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

Тестирование — важная составляющая процесса разработки ПО. Вне зависимости от того, осознаём
ли мы это или нет, мы проводим тестирование на протяжении всего процесса разработки приложения.
К примеру, при написании PHP-класса мы используем `echo` или `die` для того, чтобы проверить
корректность выполнения метода. При создании страницы, содержащей сложные HTML-формы, мы вводим
некоторые тестовые данные, чтобы проверить её работу. Более опытные разработчики напишут код,
автоматизирующий этот процесс и дающий возможность выполнить все тесты автоматически за один раз.
Этот процесс называется *автоматизированное тестирование* и является главной темой данного раздела.

В Yii поддерживается *модульное тестирование* и *функциональное тестирование*.

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

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


Разработка через тестирование
-----------------------------

Ниже приведён цикл [разработки через тестирование (TDD)](http://ru.wikipedia.org/wiki/Test-Driven_Development):

 1. Создаём новый тест, описывающий функциональность планируемой возможности. Тест должен при первом запуске
 завершиться неудачей, так как сама возможность ещё не реализована.
 2. Запускаем все тесты. Проверяем, что все они завершились неудачно.
 3. Пишем код, который проходит тесты.
 4. Запускаем все тесты. Проверяем, что все они завершились удачно.
 5. Рефакторим написанный код и проверяем, что он всё ещё проходит тесты.

Повторяем шаги 1 — 5 для новой функциональности.


Настройка тестового окружения
-----------------------------

Тестирование в Yii требует установленного [PHPUnit](http://www.phpunit.de/) 3.5+ и
[Selenium Remote Control](http://seleniumhq.org/projects/remote-control/) 1.0+.
Как устанавливать PHPUnit и Selenium Remote Control вы можете прочитать в их
документации.

При использовании консольной команды `yiic webapp` для создания нового приложения
генерируются следующие директории, позволяющие писать и выполнять тесты:

~~~
testdrive/
   protected/                файлы приложения
      tests/                 тесты
         fixtures/           фикстуры БД
         functional/         функциональные тесты
         unit/               модульные тесты
         report/             отчёты по покрытию кода тестами
         bootstrap.php       загрузчик
         phpunit.xml         конфигурация для PHPUnit
         WebTestCase.php     базовый класс для функциональных тестов страниц
~~~

Как показано выше, код тестов главным образом находится в трёх директориях:
`fixtures`, `functional` и `unit`. Директория `report` используется для хранения
генерируемых отчётов о покрытии кода тестами.

Для того, чтобы запустить тесты (как модульные, так и функциональные), необходимо
выполнить следующие команды в консоли:

~~~
% cd testdrive/protected/tests
% phpunit functional/PostTest.php // запускает отдельный тест
% phpunit --verbose functional    // запускает все тесты в директории 'functional'
% phpunit --coverage-html ./report unit
~~~

Последняя команда выполнит все тесты в директории `unit` и создаст отчёт о покрытии кода в
директории `report`. Стоит отметить, что для отчётов требуется установленное
[расширение xdebug](http://www.xdebug.org/).


Загрузчик тестов
----------------

Давайте посмотрим, что может находиться в файле `bootstrap.php`. Мы уделяем ему большое внимание,
так как он играет такую же роль, как [входной скрипт](/doc/guide/basics.entry) и является
стартовой точкой при запуске набора тестов.

~~~
[php]
$yiit='path/to/yii/framework/yiit.php';
$config=dirname(__FILE__).'/../config/test.php';
require_once($yiit);
require_once(dirname(__FILE__).'/WebTestCase.php');
Yii::createWebApplication($config);
~~~

В приведённом коде мы сначала подключаем файл `yiit.php`, который инициализирует
некоторые глобальные константы и подключает необходимые базовые классы тестов.
Затем мы создаём экземпляр приложения, используя файл конфигурации `test.php`.
Конфигурация в нём наследуется от `main.php` и добавляет компонент
`fixture` (класс [CDbFixtureManager]). Фикстуры будут детально описаны в
следующем разделе.

~~~
[php]
return CMap::mergeArray(
	require(dirname(__FILE__).'/main.php'),
	array(
		'components'=>array(
			'fixture'=>array(
				'class'=>'system.test.CDbFixtureManager',
			),
			/* раскомментируйте, если вам нужно подключение к тестовой БД
			'db'=>array(
				'connectionString'=>'DSN для БД',
			),
			*/
		),
	)
);
~~~

При запуске тестов, включающих работу с базой данных, необходимо
переопределить БД для того, чтобы не испортить реальные данные или данные,
используемые при разработке. Для этого необходимо раскомментировать конфигурацию `db`
выше и указать DSN тестовой базы в свойстве `connectionString`.

При помощи такого входного скрипта при запуске тестов мы получаем экземпляр приложения,
максимально приближённый к реальному. Главное отличие в том, что в нём есть поддержка
фикстур и используется тестовая БД.