Тестування
==========

Тестування - важлива складова процесу розробки ПЗ. Незалежно від того, усвідомлюємо ми це чи ні, ми проводимо тестування протягом всього процесу розробки додатка. Наприклад, при написанні 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`.

За допомогою такого вхідного скрипта при запуску тестів ми отримуємо примірник додатка, максимально наближений до реального. Головна відмінність в тому, що у ньому є підтримка фікстур і використовується тестова БД.