Модульне тестування =================== Оскільки тестована частина Yii побудована на [PHPUnit](http://www.phpunit.de/), рекомендується спочатку вивчити [документацію PHPUnit](http://www.phpunit.de/manual/current/en/index.html), щоб отримати загальне уявлення про те, як писати модульні тести. Далі ми наведемо основні принципи написання модульних тестів в Yii: * Модульний тест — це клас `XyzTest`, що успадковує клас [CTestCase] або [CDbTestCase], де `Xyz` — назва тестованого класу. Наприклад, для тестування класу `Post` за угодою ми називаємо відповідний клас модульного тесту `PostTest`. Базовий клас [CTestCase] призначений для загального модульного тестування, а клас [CDbTestCase] — для тестування класів моделей [Active Record](/doc/guide/database.ar). Ми можемо використовувати всі методи цих класів, успадкованих від класу `PHPUnit_Framework_TestCase`, оскільки він — предок обох класів ([CTestCase] і [CDbTestCase]). * Клас модульного тесту зберігається в PHP-файлі з імʼям `XyzTest.php`. За угодою файл модульного тесту може бути збережено в директорії `protected/tests/unit`. * Основний зміст тестового класу — набір тестових методів з іменами виду `testAbc`, де `Abc`— часто імʼя тестованого методу класу. * Зазвичай тестовий метод містить послідовність виразів тверджень (наприклад, `assertTrue`, `assertEquals`), які служать контрольними точками при перевірці поведінки цільового класу. Далі ми опишемо, як писати модульні тести для класів моделей [Active Record](/doc/guide/database.ar). Ми розширюємо наші тестові класи, наслідуючи їх від класу [CDbTestCase], оскільки він забезпечує підтримку фікстур бази даних, які ми представили у попередньому розділі. Припустимо, що ми хочемо перевірити клас моделі `Comment` у [демо-блозі](http://www.yiiframework.com/demos/blog/). Почнемо зі створення класу `CommentTest` і збережемо його у файлі `protected/tests/unit/CommentTest.php`: ~~~ [php] class CommentTest extends CDbTestCase { public $fixtures=array( 'posts'=>'Post', 'comments'=>'Comment', ); … } ~~~ У цьому класі ми визначаємо змінну-член класу `fixtures` масивом, що містить перелік фікстур, що використовуються в даному тесті. Масив являє собою відображення імен фікстур на імена класів моделей або імена таблиць фікстур (наприклад, фікстура з імʼям `posts` на клас моделі `Post`). Зауважимо, що при відображенні на імʼя таблиці фікстури ми повинні використовувати імʼя таблиці з префіксом `:` (наприклад, `:Post`), щоб відрізняти його від імені класу моделі. А при використанні імен класів моделей, відповідні таблиці будуть розглядатися у якості таблиць фікстур. Як описано вище, таблиці фікстур будуть скинуті в деякий відомий стан щоразу при виконанні тестового методу. Імʼя фікстури дозволяє нам отримати зручний доступ до даних фікстури у тестових методах. Наступний код показує типове використання: ~~~ [php] // повертає всі рядки таблиці фікстур `Comment` $comments = $this->comments; // повертає рядок з псевдонімом 'sample1' у таблиці фікстур `Post` $post = $this->posts['sample1']; // повертає екземпляр класу AR, що представляє рядок даних фікстури 'sample1' $post = $this->posts('sample1'); ~~~ > Note|Примітка: Якщо фікстура оголошена з використанням імені її таблиці (наприклад, `'posts'=>':Post'`), то третій приклад в коді вище не є допустимим, оскільки ми не маємо інформації про те, який клас моделі асоційований з таблицею. Далі ми пишемо метод `testApprove` для тестування методу `approve` в класі моделі `Comment`. Код дуже прямолінійний: спочатку ми вставляємо коментар зі статусом очікування, потім перевіряємо, коментар має статус очікування або інший, витягуючи його з бази даних, і, нарешті, ми викликаємо метод `approve` і перевіряємо, чи змінився статус, як очікувалося. ~~~ [php] public function testApprove() { // вставити коментар до листа очікування $comment=new Comment; $comment->setAttributes(array( 'content'=>'comment 1', 'status'=>Comment::STATUS_PENDING, 'createTime'=>time(), 'author'=>'me', 'email'=>'me@example.com', 'postId'=>$this->posts['sample1']['id'], ),false); $this->assertTrue($comment->save(false)); // перевірити наявність коментаря в листі очікування $comment=Comment::model()->findByPk($comment->id); $this->assertTrue($comment instanceof Comment); $this->assertEquals(Comment::STATUS_PENDING,$comment->status); // викликати метод approve() і перевірити, що коментар затверджено $comment->approve(); $this->assertEquals(Comment::STATUS_APPROVED,$comment->status); $comment=Comment::model()->findByPk($comment->id); $this->assertEquals(Comment::STATUS_APPROVED,$comment->status); } ~~~