VCCW + WP-CLI で WordPress のユニットテスト


ユニットテストの話になるとなんか心理的なハードルがあるようですね。

でも実際にはすごく簡単に始められますし、`var_dump()` を何回も書いたり消したりすることを考えると確実に楽になります。

今回の記事では、VCCW を使った WordPress プラグインのユニットテストについて説明します。

http://vccw.cc/

VCCW を使うとてっとりばやく始めることができるのでおすすめです。

## ユニットテストで楽になること

ユニットテストは細かい確認作業を自動化してくれます。確認作業を自動化するんですから楽になるに決まってるじゃないですか。

たとえば以下のコード。

```php
function hoge( $n ) {
    if ( ! is_numeric( $n ) ) {
    	return new WP_Error( "おいこら数字を入れろや！" );
    }
	return $n + 1;
}
```

こんな関数を作った場合、何種類かの値をパラメータで渡して戻り値を `var_dump()` で確認したりしますよね。

そんな時は以下のような感じでオッケー。

```php
/**
 * @test
 */
public function hoge_test() {
    // `hoge( 1 )` の戻り値が2であることを期待
    $this->assertSame( 2, hoge( 1 ) );
    
    // 文字列が引数の時は WP_Error オブジェクトであることを期待
    $this->assertTrue( is_wp_error( hoge( "hello" ) ) );
}
```

これをめんどくさいと思うかもしれませんが、このテストコードは別に消す必要ありません。

むしろずっと残しておくべきです。

こうやって細かい確認作業を残しておくことで、開発中に `phpunit` と叩くだけで、つもりつもったテストがまとめて実行されるわけです。

関数の仕様が変わったらそれにあわせてテストコードを修正したり追加したりすればいいわけです。

バグがあったときにもそのバグを再現したテストを追記していきましょう。

どう考えても便利だと思いません？

あとなにがめんどくさいかって `var_dump()` で確認する時っていちいちブラウザでみるわけですよね。

`phpunit` って叩くだけと比べると、それは泣きたくなるほどめんどくさいです。

## 既存のプラグインにユニットテストを追加

VCCW を使えばユニットテスト環境を構築するのは簡単です。

まず、ゲストマシンに入ってください。

```
$ vagrant ssh
```

次にプラグインがあるディレクトリまで移動。ここから先のコマンドはゲストマシンの中でやることに注意。

```
$ cd /var/www/html/wp-content/plugins/hoge
```

そこで以下のコマンドを実行してください。

```
$ wp scaffold plugin-tests hoge
```

最後の `hoge` はプラグインのディレクトリ名。WordPress ではこれを slug とも呼びます。

公式ディレクトリにプラグインを登録する際にプラグイン名は後からでも変更できますが、この slug は変更できないので注意しましょう。

以上で、テスト用のファイルもろもろができました。

あとはテストを実際に実行するために必要な WordPress が必要です。

このテスト用の WordPress は他のプラグインが入ってたりデータベースにゴミデータが入っていないまっさらな状態であるべきで、そういう環境を以下のコマンド一発で用意できます。

```
$ install-wp-tests
```

このコマンドはテスト用のファイルが生成されたプラグインのディレクトリの直下じゃないとエラーが出るので注意。

あとセットアップされた WordPress はゲストマシンの再起動のたびに消えて無くなります。これはバグとかではなくて、常に綺麗である必要があるからです。

以上で準備はできました。

ユニットテストを実行してみましょう。

```
$ phpunit
```

まだテストは一切書いてないですが、たったのこれだけでもこのプラグインは WordPress で有効化された状態でテストが実行されますので、構文エラーは検出できます。

## テストコード付きの WordPress プラグインをいちから作成

本来であればテストはプラグインを作りながら同時進行で書いていくべきです。

そうすることで、テストしやすい構造のプラグインができて、より信頼性が高いものになっていくわけです。

作業効率もいいです。ブラウザでの確認作業が激減しますからね。

WP-CLI をつかえばこれも簡単です。

先ほどと同じように VCCW にログイン。

```
$ vagrant ssh
```

その後でテスト用のファイル付きのプラグインを以下のコマンドで作成します。

```
$ wp scaffold plugin foo
```

これだけで、プラグインの雛形が以下のディレクトリにできているはずです。

```
$ cd /var/www/html/wp-content/plugins/foo
```

先ほどと同じようにテスト用のまっさらな WordPress を用意。

```
$ install-wp-tests
```

最後にユニットテストを実行。

```
$ phpunit
```

## テストを書く

テストは、`test-sample.php` というファイルがありますので、そこに追記していくとこから始めるといいですね。

テストファイルは、このサンプルのように `test-*.php` みたいなファイル名であれば、全部がまとめて実行されます。

大きなプラグインなら、工夫して複数のファイルに分けておくといいです。

サンプルには以下のようなテストが書かれています。

```php
class SampleTest extends WP_UnitTestCase {

    /**
     * A single example test.
     */
    function test_sample() {
            // Replace this with some actual testing code.
            $this->assertTrue( true );
    }
}
```

このテストは `true` は `true` であることって意味です。あたりまえですね。笑

ためしに `true` の部分を `false` に書き換えるとテストがコケます。ぜひ試してみましょう。

```
$ phpunit 

F                                                                   1 / 1 (100%)

Time: 2.21 seconds, Memory: 26.00MB

There was 1 failure:

1) SampleTest::test_sample
Failed asserting that false is true.

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

`$this->assertTrue()` というのはアサーションと言います。この場合、このメソッドの引数に渡された値が `true` であれば合格。そうでなければ不合格となります。

他にもよく使うのは `$this->assertSame()` というのがあります。これは第1引数と第二引数が同じであれば合格です。

```php
class SampleTest extends WP_UnitTestCase {

	/**
	 * A single example test.
	 */
	function test_sample() {
	        // Replace this with some actual testing code.
	        $this->assertTrue( true );
	}
	
	/**
	 * @test
	 */
	function test_option() {
	    update_option( "foo", "hello" );
	    $this->assertSame( "hello", get_option( "foo" ) );
	}
}
```

上の例ではもともとあるテストの下に二つ目のテストを追加しました。

テストの内容は、`update_option()` であらかじめオプションを追加しておいて、同じ値を `get_option()` で取得できているかを `$this->assertSame()` でチェックしています。

テストコードの中では WordPress の関数がそのまんま動作するということがミソです。

テスト用のメソッドを追加するときには、メソッド名が `test_` ではじまっているか、その上のコメントで `@test` というアノテーションがセットされていればオッケーです。

アサーションやアノテーションについてはいろいろありますので、PHPUnit のマニュアルをみながら徐々に覚えていくといいと思います。

https://phpunit.de/manual/current/ja/

## WP_UnitTestCase について

テスト用のファイルをよく見ると、`WP_UnitTestCase` のサブクラスであることがわかります。

`WP_UnitTestCase` というのは、WordPress 本体のユニットテスト用に開発されているクラスで、WordPress に特化した便利なメソッドがいろいろとあります。

たとえば、ダミーの記事を10件ほど放り込みたい場合は以下のような感じの記述をテストに追加します。

```php
$this->factory->post->create_many( 10 );
```

ほかにもダミーのユーザーや画像をつっこんだりとかもできるんですが、残念ながらこのクラスに関するドキュメントは存在していません。。。

以下の URL のあたりをのぞいてみてください。

https://core.trac.wordpress.org/browser/trunk/tests/phpunit/includes

あと、Qiita にタグをつけて書いているんですが僕しかいません。。。w

さみしいのでみんなで書こうぜー。

http://qiita.com/tags/WP_UnitTestCase

具体的なテストのサンプルを見たいときは以下のURLのあたりをみるといいです。

#### WordPress 本体のユニットテスト

https://core.trac.wordpress.org/browser/trunk/tests/

#### ユニットテストが書かれているプラグイン

* https://github.com/miya0001/oembed-gist
* https://github.com/miya0001/simple-map
* https://github.com/torounit/pppp
* https://github.com/torounit/custom-post-type-permalinks

最近では海外の有名プラグインのほとんどでユニットテストが書かれているので、よく使うプラグインのテストを参考にするとわかりやすいかもですね。

いろいろなテストを追加しながら小一時間あそんでみるともうこれなしでは生きていけないはずです。