CakepPHPでユニットテスト 〜コントローラ偏〜

CakePHPユニットテストのモデルのテストについて以前記載した。 基本の導入については、以前の記事を参照。

CakepPHPでユニットテスト 〜モデル偏〜

■コントローラのテスト

今回想定している簡単なアプリケーション仕様を説明。

1.ユーザーが「ユーザー名」を入力して、ボタンを押す。
2.訪問数をDBに記録

1.以下コントローラをテストする

app/controllers/posts_controller.php

以下のadd()」のテストをする。

<?php
/**
 *
 * 処理リスト
 *  ・POST  
 *  
 * @package controllers
 * @author  moritaro
 * @version 1.0
 */
class PostsController extends AppController {

    /** コントローラ 名前 */
    var $name = 'Posts';

    /** 使うモデル*/
    var $uses = array( "Entry" );

        /** コンポーネント */
    var $components = array();  

    /** 使うヘルプ */
    var $helpers = array();

    /** レイアウト */
    var $layout = 'front';

       /**
     * データPOST アクション
     * moritaro
     *
     * @param なし
     * @return なし
     */
    function add () {       

        if( !empty( $this->data ) )
                {
                        $this->Entry->setValidation( "add" );
                        $this->Entry->set( $this->data );

                        if ($this->Entry->validates())
                        {
                            if ( $this->Entry->_isExistUser( $this->data['Entry']['user'] ))
                            {
                                /** ユーザー存在の場合、回数カウント+1 */
                                $options['conditions'] = array(
                                    'Entry.user' => $this->data['Entry']['user'],
                                );
                                $data['count'] = $this->Entry->_getUsercount($this->data['Entry']['user'])+1;
                            } else {
                                /** ユーザー存在しない場合、DB新規登録 */
                                $data['count'] = 1;
                            }
                            $data['user'] = $this->data['Entry']['user'];
                            $this->Entry->save($data);
                        }
                }
                $this->render("index");
    }
}
?>

※テスト用DB設定と、テストデータ(fixtures)については、以前のものを流用。

1.テストコード

今回は、上記「add」アクションで、

『同じuserをPOSTされたら、テーブルのcountが1つアップすること』

をテストしてみる。

DB値

ユーザー:a 訪問数:1

POST値

ユーザー名:a

app/tests/cases/controllers/posts_controller.test

<?php
/**
 * Posts コントローラ TEST
 * 物理名 posts_controller
 *  
 * @package controller
 * @author  moritaro
 * @version 1.0
 */

App::import('Controller', 'Posts');

class TestPostsController extends PostsController {

    var $autoRender = false;

    function redirect($url, $status = null, $exit = true) {
        $this->redirectUrl = $url;
    }

    function render($action = null, $layout = null, $file = null) {
        $this->renderedAction = $action;
    }

    function _stop($status = 0) {
        $this->stopped = $status;
    }

}

class PostsControllerTestCase extends CakeTestCase {
    var $fixtures = array('app.entry');

        function startTest() {
        $this->Posts =& new TestPostsController();
        $this->Posts->constructClasses();
        $this->Entry =& ClassRegistry::init('Entry');
    }

    function endTest() {
        unset($this->Posts);
        ClassRegistry::flush();
    }

    function testAddCountup() {

        //POST前データ取得
        $options['conditions'] = array(
        'Entry.user' => "a",
           );
        $beforedata = $this->Entry->find("first",$options);
        //想定POSTデータ
        $this->Posts->data = array(
        'Entry' => array(
            'user' => 'a',
         ),
        );

        //コントローラのメソッド実行
        $this->Posts->index();

        //POST後データ取得
        $afterdata = $this->Entry->find("first",$options);

        //「POST前のcount+1とPOST後のcountが同じであること」がテスト成功条件
        $this->assertEqual($afterdata['Entry']['count'],$beforedata['Entry']['count']+1);

   }

}

コントローラのテストでは、CakePHPで自動処理されるいくつかの機能をoverrideする。

「redirect」は、リダイレクトしないようにする。 これは、テスト実行時に、テスト判定に限らずリダイレクトしてしまうのを防ぐため。

「render」は、オートレンダーをしないようにする。これは、VIEWへのレンダーをせずにアクションで処理のみを実行させるため。

「_stop」は、スクリプトの実行停止をしないようにする。

それから、モデルのインスタンス化や、コントローラの事前処理は終わっていることを前提として行うテストとしている。

「assertEqual」 で、予想した結果と、メソッドの実行結果が同じであるかをテスト。 つまり、『「訪問数:1」の「ユーザー:a」が、ボタンを押した場合、DBの値「訪問数:1」が1カウント増える』ことをテスト。

2.テスト実行

2−1.「http://xxxxx/test.php」にアクセスし、さきほどの画面を表示し、赤枠部分の「Test Cases」をクリック。

2−2.以下の画面が表示されるので、先ほど作成したコントローラのテストである「controllers / PostsController」をクリック。

2−3.テスト結果表示 テストが成功したら、以下のようにグリーンのバーが表示されます。 このサンプルでは、1つのメソッドがcompleteした表示となってる。 もし失敗した場合、レッドのバーが表示されます。

 

コントローラのテストは、公式ページの例だと、メソッドの実行結果を取得しているだけなのでテストになっていない。 このため、参考サイトを元に少し調整した。 また、viewにセットした値は、「viewVars」というメソッドに入るため、これを表示するテストを行うと、viewに想定したデータが正しく渡せているかを確認することが出来る。

function testDisplay() {          $this->Posts->index();         $result = $this->Usos->viewVars;         var_dump($result); }

次回は、ヘルパー、ビュー、ビヘイビア、コンポーネントなどのテストも順番に紹介してみよう。(時期は明確じゃない・・・)

【参考サイト】 Testing CakePHP Controllers the hard way コントローラからビューに渡る変数をアサーションする 公式マニュアル