FuelPHP【チュートリアル】-- コントローラーのテストの方法 --


FuelPHPのコントローラーのテストの書き方がなかったので試して見た


## 環境

* centos6.3
* fuelPHP1.5.3

## 事前準備に必要なもの
* php5.3以上
* mysql
* fuelPHPがインストール済みであること インストールをしていない場合は[FuelPHP【入門】-- CRUDを作った時のメモ(インストールからCRUD作成まで) --](http://qiita.com/items/ae107a96699745a02560)を参考にインストールしてください。

## 参考にしたサイト
* [日本語版ドキュメント(1.5ドキュメント)](http://fuelphp.jp/docs/1.5/)
* [FuelPHPでControllerのUnitTest](http://takl.org/categories/fuelphp/fuelphpphpunitcontrollerunit-test)


## testコントローラーの配置場所

デフォルトでfuel/app/tests/controllerのディレクトリが作成済みですのでそこにコントローラーのテストクラスを作成していきます。


```tree
fuel/app/tests
      ├── controller
      │   └── auth.php
      ├── model
      └── view
```

## コントローラー側

コントローラー側でテストをする際はView側にアサインした値の検証が出来れば大体のことはテストできると思います。そこでこんなサンプルを作ります。

```php:fuel/app/classes/controller/hoge.php
<?php

class Controller_Hoge extends Controller_Hybrid
{
	public function before()
	{
		parent::before();
	}

	public function action_fuga()
	{
		$this->template->title = 'htmlでのtitileタグ';
		$this->template->content = View::forge('hoge/fuga');
		//CSSを追加する
		$this->template->add_css = array('hoge.css');
	}	
}
```



## コントローラーテストクラスの作成

コントローラーの雛形です。


```php:fuel/app/tests/controller/hoge.php
/**
 * Tests for hoge
 *
 * @group App
 * @group Controller
 * @group Hoge
 */
class Test_Controller_Hoge extends TestCase
{
	public function setup()
	{

	}
}
```

## 値を検証する方法

先ほど作ったController_Hogeのadd_cssの値を検証する場合

```php:fuel/app/tests/controller/hoge.php
	/**
	 * @test
	 * @group hogecontroller
	 **/
	public function test_add_cssの値が入っているか確認する()
	{
		$expected = array('hoge.css');

		$response = Request::forge('hoge/fuga')
						     ->execute()
						     ->response();

		$assertValue = $response->body->add_css;

		$this->assertSame($expected, $assertValue);
	}
```

上記でoilコマンドを実行すればOKが返ってきます

```shell
php oil t --group=hogecontroller

Tests Running...This may take a few moments.
PHPUnit 3.7.18 by Sebastian Bergmann.

Configuration read from /home/web/lo.fuel.base.org/fuel/app/phpunit.xml

.

Time: 0 seconds, Memory: 5.25Mb

OK (1 test, 1 assertion)
```

## controller内でのRedirect()を実行の場合

FuelPHPではRedirect()を実行するとexitが入っていてテスト自体も止まってしまいます

```php:fuel/app/classes/controller/hoge.php
<?php

class Controller_Hoge extends Controller_Hybrid
{
	public function action_fugaredirect()
	{
		$this->template->is_error = true;
		//Response::redirectの中身でexitを実行しているので止まってしまう
		return Response::redirect('error/404');
	}
}
```

fuel/core/response.php

```php:fuel/core/classes/response.php
	public static function redirect($url = '', $method = 'location', $code = 302)
	{
		$response = new static;

		$response->set_status($code);

		if (strpos($url, '://') === false)
		{
			$url = $url !== '' ? \Uri::create($url) : \Uri::base();
		}

		strpos($url, '*') !== false and $url = \Uri::segment_replace($url);

		if ($method == 'location')
		{
			$response->set_header('Location', $url);
		}
		elseif ($method == 'refresh')
		{
			$response->set_header('Refresh', '0;url='.$url);
		}
		else
		{
			return;
		}

		$response->send(true);
		exit; ##<= テストを止めてしまう
	}
```

そこでresponse.phpを独自のpackageで作成してテストのときは止めないようにしてみましょう。

```php:fuel/packages/my/classes/response.php
namespace My;

class Response extends \Fuel\Core\Response
{
	/**
	 * Override Fuel\Core\Response redirect method
	 *
	 * @param   string  $url     The url
	 * @param   string  $method  The redirect method
	 * @param   int     $code    The redirect status code
	 *
	 * @return  void
	 */
	public static function redirect($url = '', $method = 'location', $code = 302)
	{
		$response = new static;
		$response->set_status($code);

		if (strpos($url, '://') === false)
		{
			$url = $url !== '' ? \Uri::create($url) : \Uri::base();
		}

		strpos($url, '*') !== false and $url = \Uri::segment_replace($url);

		if ($method == 'location')
		{
			$response->set_header('Location', $url);
		}
		elseif ($method == 'refresh')
		{
			$response->set_header('Refresh', '0;url='.$url);
		}
		else
		{
			return;
		}

		//テストではない場合はexitを実行
		if (\Fuel\Core\Fuel::$env != 'test')
		{
			$response->send(true);
			exit;
		}

		$response->send(true);
	}
}
```

そしてこのクラスをロードするようにfuel/app/config/config.phpに追加します

```php:fuel/app/config/config.php
		'packages'  => array(
			'my', //追加する
		),
```

## redirectを実行したコントローラーのテストを実行してみる

先ほどのコントローラーでアサインしたis_errorでアサートできるかテストを書いてみましょう

### コントローラー側

```php:fuel/app/classes/controller/hoge.php
<?php

class Controller_Hoge extends Controller_Hybrid
{
	public function action_fugaredirect()
	{
		$this->template->is_error = true;
		return Response::redirect('error/404');
	}
}
```

### テスト側

```php:fuel/app/tests/controller/hoge.php
	/**
	 * @test
	 * @group hogeredirect
	 **/
	public function test_is_errorがtrueか？()
	{
		$expected = true;

		$_GET = array('username' => 'hoge', 'password' => 'huga');
		$response = Request::forge('auth/account')
						   ->execute()
						   ->response();

		$assertValue = $response->body->is_error;
		$this->assertSame($expected, $assertValue);
	}
```

### テスト実行

```shell
php oil t --group=hogeredirect

Tests Running...This may take a few moments.
PHPUnit 3.7.18 by Sebastian Bergmann.

Configuration read from /home/web/lo.fuel.base.org/fuel/app/phpunit.xml

.

Time: 0 seconds, Memory: 5.25Mb

OK (1 test, 1 assertion)
```

テストが動きました。