Модульное тестирование

Поскольку тестировочная часть Yii построена на PHPUnit, рекомендуется сначала изучить документацию PHPUnit, чтобы получить общее представление о том, как писать модульные тесты. Далее мы приведём основные принципы написания модульных тестов в Yii:

Далее мы опишем, как писать модульные тесты для классов моделей 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);
}