ユニットテストの話になるとなんか心理的なハードルがあるようですね。
でも実際にはすごく簡単に始められますし、var_dump()
を何回も書いたり消したりすることを考えると確実に楽になります。
今回の記事では、VCCW を使った WordPress プラグインのユニットテストについて説明します。
VCCW を使うとてっとりばやく始めることができるのでおすすめです。
ユニットテストで楽になること
ユニットテストは細かい確認作業を自動化してくれます。確認作業を自動化するんですから楽になるに決まってるじゃないですか。
たとえば以下のコード。
function hoge( $n ) {
if ( ! is_numeric( $n ) ) {
return new WP_Error( "おいこら数字を入れろや!" );
}
return $n + 1;
}
こんな関数を作った場合、何種類かの値をパラメータで渡して戻り値を var_dump()
で確認したりしますよね。
そんな時は以下のような感じでオッケー。
/**
* @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
みたいなファイル名であれば、全部がまとめて実行されます。
大きなプラグインなら、工夫して複数のファイルに分けておくといいです。
サンプルには以下のようなテストが書かれています。
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引数と第二引数が同じであれば合格です。
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 のマニュアルをみながら徐々に覚えていくといいと思います。
WP_UnitTestCase について
テスト用のファイルをよく見ると、WP_UnitTestCase
のサブクラスであることがわかります。
WP_UnitTestCase
というのは、WordPress 本体のユニットテスト用に開発されているクラスで、WordPress に特化した便利なメソッドがいろいろとあります。
たとえば、ダミーの記事を10件ほど放り込みたい場合は以下のような感じの記述をテストに追加します。
$this->factory->post->create_many( 10 );
ほかにもダミーのユーザーや画像をつっこんだりとかもできるんですが、残念ながらこのクラスに関するドキュメントは存在していません。。。
以下の URL のあたりをのぞいてみてください。
あと、Qiita にタグをつけて書いているんですが僕しかいません。。。w
さみしいのでみんなで書こうぜー。
具体的なテストのサンプルを見たいときは以下のURLのあたりをみるといいです。
WordPress 本体のユニットテスト
ユニットテストが書かれているプラグイン
- 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
最近では海外の有名プラグインのほとんどでユニットテストが書かれているので、よく使うプラグインのテストを参考にするとわかりやすいかもですね。
いろいろなテストを追加しながら小一時間あそんでみるともうこれなしでは生きていけないはずです。