CakePHP(PHPUnit)でユニットテストを書いているのですが、コントローラーで意図したページに正しく画面遷移しているかどうかをテストしたくなり、どうやったら実現できるか試してみました。
例えば下記のページに遷移することをテストしたい場合。
itemsに関連するModel, Controller, Viewが存在する状態とします(今回はbakeで作った)。
一般的かどうかはわかりませんが、返ってきたHTML文字列の中に「商品一覧画面」という文言が存在するかどうかで判定することにしました。
テストの実行は画面から確認します。
http://localhost/test.php
テストコード
まずはシンプルにこんな感じ。
これは$resultがnullなためFailedになります。
ItemsControllerTest.php
1 2 3 4 5 |
public function testIndex() { $result = $this->testAction("/items"); debug($result); $this->assertTextContains('商品一覧画面', $result); } |
どうやらプロダクトコード側で$this->render()の結果をreturnしてあげればViewが返るみたいですね。
ItemsController.php
1 2 3 4 5 |
public function index() { $this->Item->recursive = 0; $this->set('items', $this->Paginator->paginate()); return $this->render(); } |
これでAssertionが通るのですが、一つ問題が。
この場合、Controllerの実装の全てに return $this->render() をやってあげなきゃいけないことです。
テストのためにコードを足すなんてことは本末転倒なので、これは避けたい。
下記のようにすればreturnせずにviewがとれるので、プロダクトコードに修正を入れる必要がなくなります。
ItemsControllerTest.php
1 2 3 4 5 |
public function testIndex() { $this->testAction("/items", array('return' => 'view')); debug($this->view); $this->assertTextContains('商品一覧画面', $result); } |
redirectしている場合
続いてリダイレクトする場合のテストです。
今回は商品登録画面で登録に成功すると一覧画面にリダイレクトするという仕様でいきます。
redirectした場合もindexと同様にテスト出来るかと思ったけどダメでした。
postするtestActionを実行してみる。パジェロ欲しかったけどタワシならもらえそうです。
ItemsController.php
1 2 3 4 5 6 7 8 9 10 11 |
public function add() { if ($this->request->is('post')) { $this->Item->create(); if ($this->Item->save($this->request->data)) { $this->Session->setFlash(__('The item has been saved.')); return $this->redirect(array('action' => 'index')); } else { $this->Session->setFlash(__('The item could not be saved. Please, try again.')); } } } |
ItemsControllerTest.php
1 2 3 4 5 6 7 8 |
public function testIndex() { $this->testAction('/items/add', array('return' => 'view', 'method' => 'post', 'data' => array( "name" => "タワシ", "count" => 3, "description" => "パジェロは当たりませんでした" ))); $this->assertTextContains('商品一覧画面', $this->view); } |
これは、$this->viewがブランクで返ってくるためFailedになります。
redirectの場合はviewがとれないもんなのかな。
viewがとれそうもなかったのですが、レスポンスヘッダーが取れるみたいなので、urlのlocationでリダイレクト先を確認することにしました。
と同時に、登録完了時の文言がflashされているのでそれもテストします。
ItemsControllerTest.php
1 2 3 4 5 6 7 8 9 10 11 12 |
public function testAdd() { $this->testAction('/items/add', array('method' => 'post', 'data' => array( "name" => "タワシ", "count" => 3, "description" => "パジェロは当たりませんでした" ))); $flash = CakeSession::read('Message.flash'); debug($flash); debug($this->headers); $this->assertTextContains('The item has been saved.', $flash['message']); $this->assertRegExp("/\/items$/", $this->headers["Location"]); } |
これでControllerのリダイレクト時の遷移もテスト出来ていると言えるのではないでしょうか。
もっとテストをサクサクかけるようになりたいですね!

原田 敦

最新記事 by 原田 敦 (全て見る)
- Rails Engineでブログ機能追加するgemを作る - 2015年3月15日
- WEBエンジニア一人だけでサービスを作りきる方法-夫婦のための自動ごはん予定お知らせサービス「GoHaaan」制作でやったこと - 2015年3月7日
- CentOS6でMariaDBのDynamic Columnsを試してみた - 2015年2月28日