PHPUnit + Guzzleで WebAPIのテストを書く


今までWebAPIのテストは[Frisby + jasmine-node](http://qiita.com/zaburo/items/8f967acd26ea08e2a54a)で書いていましたが、PHPでも書いてみます。
なお、WebAPIにリクエストするライブラリとしてGuzzleを利用してみたいと思います。Guzzleは直感的でかつ、非同期や様々なオプションに対応していてすばらしいです。

WebUIのテストについては[こちら](http://qiita.com/zaburo/private/f11357170953a3c34b8f)。

##前提

* composerがインストールされている
* Mac(El capitan)

ホームディレクトリ内にtestというフォルダを作ってその中で作業するものとします。

##準備

###ライブラリのダウンロード

```bash
#ディレクトリ作成
cd ~/
mkdir test
cd test

#phpunitとguzzleのインストール
composer require phpunit/phpunit
composer require guzzlehttp/guzzle
```

>guzzeleはVer5以上からguzzle/guzzleからguzzlehttp/guzzleになったそうです。

##テストを書く（テスト対象）

テスト対象のAPIとして下記のようなものを用意してみました。
これを、http://localhost/test/api.phpとして参照できるようにしています。

ポイントとしては、

* POST/GETに対応
* Dataは配列を戻します（DBレスポンスのイメージ）

となっていて、これをどう取得、テストできるか試してみます。

```php
<?php

	$name = "xxx";

	if(isset($_POST['name'])) $name = $_POST['name'];
	if(isset($_GET['name'])) $name = $_GET['name'];

	$data = [
		['name'=>'hoge','age'=>'30'],
		['name'=>'foo','age'=>'20']
	];


	$response = [];
	$response['status'] = "OK";
	$response['message'] = "Hello ".$name.".";
	$response['data'] = $data;


	header('Content-type: application/json');
	echo json_encode($response);
```

こんなJSONが戻ります。

```json

{
	"status":"OK",
	"message":"Hello xxx.",
	"data":
		[
			{"name":"hoge","age":"30"},
			{"name":"foo","age":"20"}
		]
}
```

##テストを書く（テストコード）

Guzzleを利用すると、非常に直感的でわかりやすいコードで書けます。
GETもPOSTもほぼ同じコードでかけることが分かります。

>guzzle5まではPOSTのパラメータ名はbodyだったようですが、6からはform_paramsとなっているようです。

```php
<?php

class sampleTest extends PHPUnit_Framework_TestCase
{
	public function testWebAPI_GET()
	{
		//
		$client = new GuzzleHttp\Client();

		//get
		$res = $client->get('http://localhost/test/api.php',[
			'query'=>[
				'name'=>'POO',
				'email'=>'poo@poo.com',
			],
		]);

		//取得 第2引数にtrueつけると連想配列
		$obj = json_decode($res->getBody());

		//取得
		$status = $obj->status;
		$message = $obj->message;
		$rows = $obj->data;

		//loop（参考）
		foreach ($rows as $row) {
			//echo $row->name;
		}

		//評価
		$this->assertEquals("OK",$status);
		$this->assertEquals("Hello POO.",$message);
		$this->assertRegExp('/^Hello.+\.$/',$message);
		$this->assertCount(2,$rows);
	}

	public function testWebAPI_POST()
	{
		//
		$client = new GuzzleHttp\Client();

		//post
		$res = $client->post('http://localhost/test/api.php',[
			'form_params'=>[
				'name'=>'POO',
				'email'=>'poo@poo.com',
			],
		]);

		//取得 第2引数にtrueつけると連想配列
		$obj = json_decode($res->getBody());

		//取得
		$status = $obj->status;
		$message = $obj->message;
		$rows = $obj->data;

		//loop（参考）
		foreach ($rows as $row) {
			//echo $row->name;
		}

		//評価
		$this->assertEquals("OK",$status);
		$this->assertEquals("Hello POO.",$message);
		$this->assertRegExp('/^Hello.+\.$/',$message);
		$this->assertCount(2,$rows);
	}
}
```

##実行

```bash
cd ~/test
./vendor/bin/phpunit --colors tests/

OK (2 tests, 6 assertions)
```
グリーンで完了しました。

###最低限のassertメソッド

* assertEquals(\$expect,\$var) $expectと$varが等しいか？
* assertRegExp(\$ptn, \$var) 正規表現にマッチするかどうか？
* assertNull(\$var)
* assertTrue(\$var)
* assertFalse(\$var)
* assertCount(\$num,\$array)
* assertEmpty(\$array)

###LaravelのQueryBuilderやEloquentを使う

UIやAPIのテストを実行した結果、DBに正常に値が書き込まれているかをチェックしたくなります。もちろん普通にPDOでコードを書いてもいいですが、Laravelに慣れてる場合、QueryBuilderやEloquentが使いたくなります。その場合は、[こちら](http://qiita.com/zaburo/items/9b8aa05c975677669142)を参考にしてください。