PHPUnit 入門

※6.3のドキュメントから引っ張ってきてます

# 規則
・クラス名は「対象名Test」
・テストを行うメソッド名は「test*」
・「PHPUnit\Framework\TestCase」を継承する
・テストはコードを上から下へなめていく

# 書き方
## 例
```php
<?php
use PHPUnit\Framework\TestCase;

class HogeTest extends TestCase
{
    public function testHoge()
    {
        $stack = [];
        $this->assertEquals(0, count($stack));
    }
}
```

## アサーション
テストの結果を判定するメソッド。
「$this->アサーションメソッド」「self::アサーションメソッド」のいずれかの方法で使用する。

引数にメッセージを指定すると、エラー時に出力してくれる。

下記で主に使うものを抜粋。

※引数で期待値と結果はどっち先に書くんだっけ　⇒　**先に期待値かく**

|メソッド|説明|
|:--|:--|
|assertEmpty(\$actual[, $message])|$actualが空なら正常|
|assertEquals(\$expected, \$actual[, $message])|\$expectedと$actualが一致すれば正常|
|assertSame(\$expected, \$actual[, $message])|assertEqualsで型もみる厳密版|
|assertNotSame(\$expected, \$actual[, $message])|assertSameの逆|
|assertTrue(\$actual[, $message])|$actualがtrueなら正常|
|assertFalse(\$actual[, $message])|$actualがfalseなら正常|
|assertNull(\$actual[, $message)|$actualがnullなら正常|

## 前処理、後処理
### テストメソッド単位
各テストメソッドの実施の度に、その前後で呼ばれる。

```php
protected function setUp()
{
  //前処理
}

protected function tearDown()
{
  //後処理
}
```

### テストクラス単位
テストケースとして、最初のテストメソッド開始前に一度のみ、
最後のテストメソッド終了時に一度だけ実行される。

```php
protected function setUpBeforeClass()
{
  //前処理
}

protected function tearDownAfterClass()
{
  //後処理
}
```

# コマンド
## 実行
```bash
phpunit [options] テストクラス名 [テスト.php]
```

⇒「テストクラス名.php」を実施。
　テストクラス名とファイル名が不一致なら、ファイルも一緒に指定する。

```bash
phpunit [options] ディレクトリ
```

⇒ディレクトリ配下のテストを実施。

## オプション
抜粋。
細かいオプションはコマンドではなく、phpunit.xmlにて設定したほうが良いので。

|オプション|説明|
|:--|:--|
|--bootstrap phpファイル|テストの前に実行される bootstrap.phpを指定します。|
|-c XMLファイル|設定を XML ファイルから読み込みます。<br /><br />phpunit.xmlがカレントディレクトリにある場合、オプションなしでも読み込まれる。|

## テストの結果の見方
|ステータス|説明|
|:--|:--|
|.|成功|
|F|アサーション失敗|
|E|テスト中にエラー発生|
|R|テストが危険？|
|S|テストを省略|
|I|テストが未完成|

# テクニック
## 依存
「@depends 依存メソッド名」をdocコメント用いると、
テストメソッドはdependsで指定したメソッドに依存しているとされ、
依存メソッドの結果を引数で受け取れる。

※テストの実施順序はかわらないため、記述順序は依存を解決するように書く

```php
function testA()
{
  $hoge = 'hoge';
  return $hoge;
}

/*
 * @depends testA
 */
function testB($hoge)
{
}
```

## データプロバイダ
1テストメソッドに対し、さまざまなテストデータを渡し、
複数のケースのテストをしたいときに使う。

```php
public function addProvider() {
  return array(
    'test1' => (1, 2, 3),
    'test2' => (2, 3, 5),
  );
}

/**
 * @dataProvider addProvider
 */
public function testHoge($a, $b, $result) {
  $this->assertEquals($result, ($a + $b));
}
```

## 未完成を明記
テストメソッドを未完成としたい場合、markTestIncomplete([メッセージ])メソッドを記載しておけばよい。

```php
public function testHoge()
{
  $this->markTestIncomplete(
    'このテストは、まだ実装されていません。'
  );
}
```

## テストの省略
環境等の問題などでテストを省略したい場合に、
markTestSkipped([メッセージ])メソッドを記載しておけばよい。

```php
public function testHoge()
{
  $this->markTestSkipped(
    '省略します'
  );
}
```

## テストダブル
モックのこと。

### createMockメソッド
いくつかのデフォルト設定を持ったモックを作成するメソッド。

```php:例
$stub = $this->createMock(SomeClass::class);
```

主なデフォルト設定は

- コンストラクタを実行しない
- 全メソッドが、nullを返すだけのダミー実装になる
- final,private,staticのメソッドは作られない

ちなみに、以下のgetMockBuilderメソッドと同等。

```php:
$stub = $this->getMockBuilder($originalClassName)
       ->disableOriginalConstructor()
       ->disableOriginalClone()
       ->disableArgumentCloning()
       ->disallowMockingUnknownTypes()
       ->getMock();
```

### getMockBuilderメソッド
createMockの挙動をカスタマイズするときに使用するメソッド。

- コンストラクタは置き換えない
- 全メソッドが、nullを返すだけのダミー実装になる

設定用メソッド

|メソッド|説明|
|:--|:--|
|getMock()|モックの取得|
|disableOriginalConstructor()|元クラスのコンストラクタを無効にする|
|setMethods($array_methods)|置き換えたいメソッドを指定。<br /><br />nullを指定すると置換しない。|
|setConstructorArgs(array $args)|コンストラクタに渡す引数を指定|
|disableOriginalClone()|元クラスのクローンコンストラクタを無効にする|
|disableAutoload()|__autoload()を無効にする|

### メソッドの戻り値を置き換える
```php
$stub = $this->createMock(SomeClass::class);

$stub->method('hoge')->willReturn('foo');
$stub->method('fuga')->will($this->returnValue('foo'));
```

#### willReturnメソッド
戻り値を設定するだけ。

#### willメソッド
細かく戻り値を設定できる。

下記に抜粋。

|メソッド|説明|
|:--|:--|
|will(\$this->returnValue($value))|戻り値に指定値をセット|
|will(\$this->returnArgument($num))|メソッドに渡された$num番目の引数を戻り値にセット|
|will(\$this->returnSelf())|戻り値に自オブジェクトをセット|
|will(\$this->throwException(new Exception))|戻り値に例外をセット|

## ReflectionClassを使う
privateなメソッドやプロパティのアクセス権限を変えてテストをしたいとき、
もしくはそれをモック化して、テストで利用したいときに使う。

```php:テスト対象のprivateなプロパティをモックで置換する
//プロパティに置換させたいモックを作成
$prop_mock = $this->getMock('HogeClass');

//テスト対象をモック化
$target = $this->getMockBuilder('Target')
  ->setConstructorArgs(array(array()))
  ->setMethods(array('Method1', 'Method2'))
  ->getMock();

//テスト対象のprivateプロパティを緩めて、モックで置換
$ref = new ReflectionClass($target); 

$prop = $ref ->getProperty('prop');
$prop->setAccessible(true); //アクセス権限をゆるくする
$prop->setValue($target, $prop_mock);
```

# phpunit.xml


# その他引っかかったこと
## 「headers already sent by」的なエラーが出たとき

**対応**
[PHPのTestでheader関数によるエラーを回避する](http://qiita.com/petitviolet/items/96e64f709f0ef7dcf612)