Testy jednostkowe

Ponieważ framework testujący w Yii zbudowany jest na bazie PHPUnit, zalecane jest wcześniejsze przejrzenie dokumentacji PHPUnit w celu uzyskania podstawowej wiedzy o pisaniu testów jednostkowych. Poniżej podsumowujemy podstawowe zasady pisania testów jednostkowych w Yii:

  • Test jednostkowy napisany jest w postaci klasy XyzTest, która dziedziczy z CTestCase lub CDbTestCase, gdzie Xyz oznacza klasę, która będzie testowana. Na przykład, aby przetestować klasę postu Post, nazwiemy odpowiadający jej test umownie PostTest. Klasa bazowa CTestCase przeznaczona jest dla ogólnych testów jednostkowych, zaś klasa CDbTestCase jest bardziej odpowiednia dla testowania klas modeli rekordu aktywnego. Ponieważ PHPUnit_Framework_TestCase jest klasą rodzica dla obu klas, możemy używać wszystkich metod dziedziczonych z tej klasy.

  • Klasa testu jednostkowego jest zapisana w pliku PHP o nazwie XyzTest.php. Zgodnie z przyjętą konwencją plik testu jednostkowego może zostać zapisany w katalogu protected/tests/unit.

  • Klasa testująca zawiera głównie zestaw metod nazwanych wg wzorca testAbc, gdzie Abc często jest nazwą testowanej metody klasy.

  • Metoda testująca zazwyczaj zawiera sekwencję wyrażeń z asercjami (np. assertTrue, assertEquals), które służą jako punkty kontrolne podczas sprawdzania zachowania obiektu klasy.

W dalszej części opiszemy przede wszsytkim jak pisać testy jednostkowe dla klas modeli rekordu aktywnego. Będziemy rozszerzać nasze klasy testujące dziedzicząc z klasy CDbTestCase gdyż dostarcza ona wsparcia dla konfiguracji testów bazodanowych, o której pisaliśmy w poprzednim rozdziale.

Załóżmy, że chcemy przetestować klasę modelu komentarza Comment z przykładowego blogu. Rozpoczynamy poprzez
utworzenie klasy o nazwie CommentTest i zapisania jej jako protected/tests/unit/CommentTest.php:

class CommentTest extends CDbTestCase
{
    public $fixtures=array(
        'posts'=>'Post',
        'comments'=>'Comment',
    );
 
    ......
}

W klasie tej, określamy zmienną fixtures jako tablicę opisującą konfiguracje testów, które będa używane przez ten test. Tablica reprezentuje mapowanie pomiędzy nazwami konfiguracji testów a nazwami modeli klas bądź też nazwami konfiguracji testów bazodanowych (np. pomiędzy nazwą konfiguracji testu posts a klasą modelu Post). Zauważ, iż podczas mapowania do nazw tabeli konfiguracji testu, poprzedzamy tabelę dwukropkiem (np. :Post) aby odróżnić ją od nazwy klasy modelu. Jeśli będziemy używać nazw klas modeli, odpowiadające im tabele będą traktowane jako tabele konfiguracji testu. Jak już opisaliśmy wcześniej, konfiguracje testu będą zresetowane do jakiegoś znanego
stanu, za każdym razem, kiedy metoda testowa jest wywoływana.

Nazwy konfiguracji testu pozwalają nam na wygodny dostęp do danych konfiguracji testu w metodach testujących. Poniższy kod przedstawia ich typowe użycie:

// zwraca wszystkie wiersze z konfiguracji testu dla tabeli komentarzy 'Comment'
$comments = $this->comments;
// zwraca wiersz, którego aliasem jest 'sample1' w konfiguracji testu dla tabeli postów `Post` 
$post = $this->posts['sample1'];
// zwraca instancję AR reprezentującą wiersz danych z konfiguracji testu 'sample1' 
$post = $this->posts('sample1');

Uwaga: Jeśli konfiguracja testu została zdefiniowana przy użyciu nazwy tabeli
(np. 'posts'=>':Post'), wtedy zaprezetnowany powyżej 3 przykład użycia jest niepoprawny, ze względu na to, iż nie posiadamy informacji jaka klasa modelu jest powiązana z tabelą.

W dalszej części opiszemy metodę testApprove testującą metodę approve w klasie modelu komentarza Comment. Kod jest bardzo prosty: najpierw wstawiamy komentarz, który posiada status "oczekujący"; następnie sprawdzamy czy komentarz ten posiada status "oczekujący" poprzez odczytanie go z bazy danych; na końcu wołamy metodę approve i sprawdzamy czy status zmienił tak jak oczekiwaliśmy.

public function testApprove()
{
    // wstaw komentarz o statusie "oczekujący"
    $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));
 
    // zweryfijuj komentarz o statusie "oczekujący"
    $comment=Comment::model()->findByPk($comment->id);
    $this->assertTrue($comment instanceof Comment);
    $this->assertEquals(Comment::STATUS_PENDING,$comment->status);
 
    // wywołaj metodę approve() i sprawdź czy komentarz znajduje się w statusie "zatwierdzony"
    $comment->approve();
    $this->assertEquals(Comment::STATUS_APPROVED,$comment->status);
    $comment=Comment::model()->findByPk($comment->id);
    $this->assertEquals(Comment::STATUS_APPROVED,$comment->status);
}
$Id: test.unit.txt 2841 2011-01-12 21:04:12Z alexander.makarow $

Be the first person to leave a comment

Please to leave your comment.