WordPressのコアのテストコードを読んでみようぜー!

WordPressで行う継続的インテグレーション入門編 from Hiroshi Urabe

先日の WordCamp Tokyo 2015 でいろいろお話させて頂きましたが、本体のテストや、そこら辺のリソースのまとめです。

WordPress本体のテストコードを取得する。

WordPressのテストコードは、WordPressの開発レポジトリから取得できます。subversion が必要なので、Xcodeとか、Windowsの人は TortoiseSVN とかインストールすればいいと思います。

んで、こんな感じで取得できます。

$ svn mkdir wordpress-develop
$ cd wordpress-develop
$ svn co https://develop.svn.wordpress.org/

サブバージョンのチェックアウトは、現在のディレクトリに直接行われるので、適当にディレクトリを作ってそこで行います。ホームディレクトリとかでやると結構悲惨です。

全部取得すると結構な時間(10分弱?)がかかるので、その場合は最新の開発版が入ってるtrunkだけ取ってくればとりあえずいいかなと思います。

その場合は、先のコマンドの最後の1行を

$ svn co https://develop.svn.wordpress.org/trunk

こんな感じに変更すればいいです。

ex: Using Subversion « WordPress Codex

ちなみに、読むだけなら、https://core.trac.wordpress.org/browser/ とかでも読めますが、開発時に補完とかあるといろいろ捗るので、チェックアウトしておくことをおすすめします。

テストコードを読んでみる

下準備

チェックアウトできたら trunkや 適当なバージョンのディレクトリに入って、testsディレクトリを覗いてみるととテストコードがあります。

phpunitとqunitがありますが、基本的にはPHPUnitを扱います。Qunit はJSのテストです。テーマカスタマイザーとかビジュアルエディタのテストが入ってます。

また、PHPUnitのソースコードをGithubあたりから引っ張ってきて、IDEとかエディタで読み込むようにするとかなり楽になります。

$ git clone https://github.com/sebastianbergmann/phpunit

読んでみる

とりあえず、全部読もうとするとパニクるので、比較的自分が取り扱ってるところから中心に読んでみるのがいいです。どこに書いてあるか解らない場合は、とりあえず関数名・クラス名で検索をかければだいたい見つかります。

よくわからないという人は、trunk/tests/phpunit/tests/rewrite.php を読んでみましょう。ひとつひとつのテストがかなり短めなので、わかりやすいかなと思います。だまされたと思って、 Tests_Rewrite:: test_url_to_postid あたりを読んでみましょう。

class Tests_Rewrite extends WP_UnitTestCase {
    /* 省略 */

    function test_url_to_postid() {

        $id = $this->factory->post->create();
        $this->assertEquals( $id, url_to_postid( get_permalink( $id ) ) );

        $id = $this->factory->post->create( array( 'post_type' => 'page' ) );
        $this->assertEquals( $id, url_to_postid( get_permalink( $id ) ) );
    }

    /* 省略 */
}

投稿を作ってそのIDと、生成されたパーマリンクから逆算した投稿IDが一致してるかどうかを検査してるだけです。読んでみるとこんなもんだったりします。

長いテストでも、製品のコードとは違って、複数の関数が絡み合ったりとかがないので、結構読みやすいです。

WP_UnitTest_Factory

テストコードを読んでいくと、

$id = $this->factory->post->create();

とか

$blog_id = $this->factory->blog->create( array( 'path' => '/example' ) );

みたいな奴がいますが、$this->factoryが、WP_UnitTest_Factory というClassのインスタンスになっています。これが便利で適当にパラメーターを突っ込むと、不足分のパラメーターを補って、投稿とか、マルチサイトのブログとか、カテゴリーとかその他もろもろを作ってくれます。

一応プロパティとして存在するのはこれだけあります。

  • WP_UnitTest_Factory::$post
  • WP_UnitTest_Factory::$attachment
  • WP_UnitTest_Factory::$comment
  • WP_UnitTest_Factory::$user
  • WP_UnitTest_Factory::$term
  • WP_UnitTest_Factory::$category
  • WP_UnitTest_Factory::$tag
  • WP_UnitTest_Factory::$blog
  • WP_UnitTest_Factory::$network

networkとかよくわからんです。が基本的には、create, create_and_get, create_many さえ知ってれば全部使えます。

WP_UnitTest_Factory_For_Thing

先ほど上げた、WP_UnitTest_Factory::$post 等の親クラスです。create 等はここに実装されています。

WP_UnitTest_Factory_For_Thing:create()

テストコード内の

$id = $this->factory->post->create();

等の親玉です。第1引数に、配列でパラメーターを突っ込めばいいです。パラメーターは、wp_insert_postとか、wp_insert_attachment とか、wp_insert_term などそのオブジェクトを生成する関数のパラメーターを渡せばいいです。生成した後、ID が返ります。

WP_UnitTest_Factory_For_Thing:create_and_get()

WP_UnitTest_Factory_For_Thing:create() とそんなに変わらないですが、返値が IDではなくオブジェクトが返ってきます。get_postで返ってくる奴だったり、get_termで返ってくる奴だったり。

WP_UnitTest_Factory_For_Thing:create_many()

オブジェクトを大量に生成するときに使います。

第1引数に生成するオブジェクトの個数、第2引数にパラメーターを設定すればその分だけ投稿とかタームとかが生成されます。戻り値はIDの配列です。

まとめ

まだまだテスト周りはいろいろクラスや関数がいたりするのですが、とりあえずダミーデータの生成が簡単にできるし、簡単に再現可能というだけでもテスト書く意義ってあると思うのでとりあえず書けばいいと思います。

あと、テストコードを読むことで、ドキュメントやソースを読むのとはまた別の角度で実装の理解が出来たりします。また、「こういう感じでテストすればいいのかー」みたいなのが解ってくると、WordPress 以外でも使えるアイデアがあったりします。

テストコード入門編にいかがでしょうか?

プラグインとか書きながらいろいろ読むと、意外な発見とかもあるのでおもしろいですよー。