Модульное тестирование
Поскольку тестировочная часть Yii построена на PHPUnit, рекомендуется сначала изучить документацию PHPUnit, чтобы получить общее представление о том, как писать модульные тесты. Далее мы приведём основные принципы написания модульных тестов в Yii:
Модульный тест — это класс
XyzTest
, наследующий класс CTestCase или CDbTestCase, гдеXyz
— название тестируемого класса. Например, для тестирования классаPost
по соглашению мы называем соответствующий класс модульного тестаPostTest
. Базовый класс CTestCase предназначен для общего модульного тестирования, а класс CDbTestCase — для тестирования классов моделей Active Record. Мы можем использовать все методы этих классов, унаследованные от классаPHPUnit_Framework_TestCase
, поскольку он — предок обоих классов (CTestCase и CDbTestCase).Класс модульного теста хранится в PHP-файле с именем
XyzTest.php
. По соглашению файл модульного теста может быть сохранен в директорииprotected/tests/unit
.Основное содержание тестового класса — набор тестовых методов с именами вида
testAbc
, гдеAbc
— часто имя тестируемого метода класса.Обычно тестовый метод содержит последовательность выражений утверждений (например,
assertTrue
,assertEquals
), служащих контрольными точками при проверке поведения целевого класса.
Далее мы опишем, как писать модульные тесты для классов моделей Active Record. Мы расширяем наши тестовые классы, наследуя их от класса CDbTestCase, поскольку он обеспечивает поддержку фикстур базы данных, которые мы представили в предыдущем разделе.
Предположим, что мы хотим проверить класс модели Comment
в
демо-блоге. Начнем с создания класса
CommentTest
и сохраним его в файле protected/tests/unit/CommentTest.php
:
class CommentTest extends CDbTestCase { public $fixtures=array( 'posts'=>'Post', 'comments'=>'Comment', ); … }
В этом классе мы определяем переменную-член класса fixtures
массивом,
содержащий список фикстур, используемых в данном тесте. Массив представляет
собой отображение имен фикстур на имена классов моделей или имена таблиц
фикстур (например, фикстуры с именем posts
на класс модели Post
). Заметим,
что при отображении на имя таблицы фикстуры мы должны использовать имя таблицы
с префиксом :
(например, :Post
), чтобы отличать его от имени класса модели.
А при использовании имен классов моделей, соответствующие таблицы будут
рассматриваться в качестве таблиц фикстур. Как описано выше, таблицы фикстур
будут сброшены в некоторое известное состояние каждый раз при выполнении
тестового метода.
Имя фикстуры позволяет нам получить удобный доступ к данным фикстуры в тестовых методах. Следующий код показывает типичное использование:
// возвращает все строки таблицы фикстур `Comment` $comments = $this->comments; // возвращает строку с псевдонимом 'sample1' в таблице фикстур `Post` $post = $this->posts['sample1']; // возвращает экземпляр класса AR, представляющего строку данных фикстуры 'sample1' $post = $this->posts('sample1');
Примечание: Если фикстура объявлена с использованием имени её таблицы (например,
'posts'=>':Post'
), то третий пример в коде выше не является допустимым, так как мы не имеем информации о том, какой класс модели ассоциирован с таблицей.
Далее мы пишем метод testApprove
для тестирования метода approve
в классе
модели Comment
. Код очень прямолинеен: сначала мы вставляем комментарий со
статусом ожидания, затем проверяем, комментарий имеет статус ожидания или
другой, извлекая его из базы данных, и, наконец, мы вызываем метод approve
и
проверяем, изменился ли статус, как ожидалось.
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); }