Laravel製 軽量フレームワーク Lumen unit test


# 趣旨

テストを試してみる

参考: http://lumen.laravel.com/docs/testing

# 始め方

##　いつもどおりにプロジェクト生成

```
lumen new test_app
```

```
test_app
├── app
│   ├── Console
│   ├── Exceptions
│   ├── Http
│   ├── Jobs
│   └── Providers
├── artisan
├── bootstrap
│   └── app.php
├── composer.json
├── composer.lock
├── composer.phar
├── database
│   ├── migrations
│   └── seeds
├── phpunit.xml
├── public
│   └── index.php
├── readme.md
├── resources
│   ├── lang
│   └── views
├── server.php
├── storage
│   ├── app
│   ├── framework
│   └── logs
├── tests
│   ├── ExampleTest.php
│   └── TestCase.php
└── vendor

```


## とりあえず、サンプルのテストを動かす

**動かなかったらvendorを削除してcomposerを利用して再インストールする**

```
#アプリケーションのディレクトリ以下で

vendor/bin/phpunit
```
 
結果は以下のとおりになるはず


```

PHPUnit 4.6.4 by Sebastian Bergmann and contributors.

Configuration read from /Users/shouhei/Dev/sample/php/lumen/test_app/phpunit.xml

.

Time: 68 ms, Memory: 5.50Mb

OK (1 test, 1 assertion)

```

## 何が動いたのか？

ドキュメントを見ると```tests```以下にテスト用のファイルを設置しろとのことなのでtests以下を見ると

```
├── tests
│   ├── ExampleTest.php
│   └── TestCase.php
```

以上があるので、まず```ExampleTest.php```を覗く

## ExampleTest.php

```php
<?php

 class ExampleTest extends TestCase {

     /**
      * A basic test example.
      *
      * @return void
      */
     public function testBasicExample()
     {
         $response = $this->call('GET', '/');

         $this->assertResponseOk();
     }

 }
```


シンプル！ なるほど、TestCaseクラスを継承して書きなさいとの事ですね。


## レッド => グリーン の流れを作る

ではまず、適当に、パラメーターを返すメソッドを作ることを想定して、テストを追記する。

(本当は別ファイルに記述したほうが良いのだけれど、面倒なので今回は追記)

以下は、/hogehogeにアクセスしたら、```hogehoge```という文字列を含むレスポンスが帰ってくることを想定。

```diff
 <?php

 class ExampleTest extends TestCase {

     /**
      * A basic test example.
      *
      * @return void
      */
     public function testBasicExample()
     {
         $response = $this->call('GET', '/');

         $this->assertResponseOk();
     }

+    public function testGet()
+    {
+        $response = $this->call('GET','/hogehoge');
+        $this->assertEquals('hogehoge',$response->getContent());
+    }
+
 }
```

実行

```
PHPUnit 4.6.4 by Sebastian Bergmann and contributors.

Configuration read from /Users/shouhei/Dev/sample/php/lumen/test_app/phpunit.xml

.F

Time: 69 ms, Memory: 5.75Mb

There was 1 failure:

1) ExampleTest::testHello
The response was not a view.
Failed asserting that false is true.

/Users/shouhei/Dev/sample/php/lumen/test_app/vendor/laravel/lumen-framework/src/Testing/AssertionsTrait.php:48
/Users/shouhei/Dev/sample/php/lumen/test_app/tests/ExampleTest.php:20

FAILURES!
Tests: 2, Assertions: 2, Failures: 1.
```

当然失敗する

```app/Http/routes.php```に追記

```diff
 <?php

 /*
 |--------------------------------------------------------------------------
 | Application Routes
 |--------------------------------------------------------------------------
 |
 | Here is where you can register all of the routes for an application.
 | It's a breeze. Simply tell Laravel the URIs it should respond to
 | and give it the controller to call when that URI is requested.
 |
 */

 $app->get('/', function() use ($app) {
     return $app->welcome();
 });
+
+$app->get('/{str}', function($str) use ($app) {
+    return $str;
+});
```

この状態でテストを実行すると以下のようになるはず。

```
PHPUnit 4.6.4 by Sebastian Bergmann and contributors.

Configuration read from /Users/shouhei/Dev/sample/php/lumen/test_app/phpunit.xml

..string(8) "hogehoge"


Time: 62 ms, Memory: 5.50Mb

OK (2 tests, 2 assertions)
```

## POSTも試す

```ExampleText.php```に追記

```diff
+public function testPost()
+{
+    $response = $this->call('POST','/',["name"=>"hogehoge"]);
+     $this->assertEquals('hogehoge',$response->getContent());
+}
```

レッドになるので```app/Http/routes.php```に追記

```diff
+ $app->post('/', function() use($app){
+     return Request::input("name");
+ });
```

この状態だとRequestクラスが使えないので、```boostrap/app.php```の```$app->withFacades();```をコメントイン


で、サーバーを起動してcurlで確認をするとpostした値が帰ってくる。

**が、**

**テストを動かすと落ちる**

どうやら[他の人](http://laravel.io/forum/04-19-2015-lumen-requestall-is-empty-when-using-this-call-in-unit-test)も同様の現象が起きているっぽい

Lumen側でリクエストは正常に受け取れるが、テストコードの```$this->call()```でPOSTリクエストを投げるとデータが消失するらしい。

[githubのissue](https://github.com/laravel/lumen-framework/issues/55)にも上がっている。

ちなみにLaravelのほうで直したのを覚えてるよーってコメントが残っていたからすぐに修正されると思う。

残念ながら、POSTのテストは断念

### 追記
2015/4/28のver 5.0.8~ でpostをテストする際のバグが修正されたみたいなので、後ほど記事を修正します。 

## view付きのテストを試す

viewに引き渡す変数と、その中身をテスト出来るので、２つテストメソッドを追加。 レスポンスのbodyをテストするメソッドは削除

```diff
 -    public function testGet()
-    {
-        $response = $this->call('GET','/hogehoge');
-        $this->assertEquals('hogehoge',$response->getContent());
-    }

+    public function testViewHas()
+    {
+        $this->call('GET','/hogehoge');
+        $this->assertViewHas('message');
+    }

+    public function testViewHasValue()
+    {
+        $this->call('GET','/hogehoge');
+        $this->assertViewHas('message','hogehoge');
+    }
```

続いてメソッドの修正

```diff
$app->get('/{str}', function($str) use ($app) {
-    return $str;
+    return view("index",['message'=>$str]);
});
```

それに伴いviewの実装

```resoureces/views/index.blade.php ```


```
<h1>{{$message}}</h1>
```

で、テストを実行できるはず。

# 終わりに

今回はroutesのテストだけで終了したが、Laravelの親戚ということもあるので、おそらくmodel周りのテストも出来るはず。