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

Поскольку тестировочная часть 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);
}

Be the first person to leave a comment

Please to leave your comment.