案件テーマ開発環境(その2 単体テスト) : WordPress

Pocket

テーマの開発で単体テストを利用するメモです。

以前、「案件テーマ開発環境 : WordPress」という記事を書きました。
その記事であまり触れなかった単体テストについて書いています。

本記事はWordPress開発環境としてVCCWを使います。
VCCWはあらかじめ下記ツールがインストールされています。

  • PHPUnit
    コマンド phpunit
  • WP_CLI
    コマンド wp

今回のディレクトリ構成

my-theme
|
|- dev
     |
     |- report  // コードカバレッジ
     |
|- inc    // 自作のクラス群(今回のテスト対象)
     |
     |- class-my-example1.php
     |
     |- class-my-example2.php
|
|- tests    // テストスイート
     |
     |- bootstrap.php
     |
     |- test-my-example1.php
     |
     |- test-my-example2.php
|
|- functions.php
|
|- index.php
|
|- phpunit.xml
|
|- style.css

単体テスト

PHPUnitを使います。
VCCWはPHPUnitがインストール済みです。

以下の処理はVCCWへログインして行います。

$ vagrant ssh

テスト環境構築の流れ

  1. プラグイン雛形作成
    最終的な目標はテーマのテストですがプラグイン用に作成したテスト雛形をテーマ用に変更して利用します。
  2. テスト環境構築
    テスト用データベース作成およびテスト用WordPressをインストールするシェルスクリプを実行します。

1.プラグイン雛形作成

WP_CLIでテストを含むプラグイン雛形を作成します。

// wp-config.phpが配置されているフォルダへ移動します(VCCWのデフォルトは/var/www/wordpress)。
$ cd /var/www/wordpress

// プラグインの雛形を作成します。
$ wp scaffold plugin my-plugin

// 作成される雛形
my-plugin
    |
    |-- bin
        |
        |-- install-wp-tests.sh
    |
    |-- tests
        |
        |-- bootstrap.php
        |
        |-- test-sample.php
        |
        |-- test-my-plugin.php
    |
    |-- .travis.yml
    |
    |-- phpunit.xml
    |
    |-- readme.txt
    |
    |-- my-plugin.php

2.テスト環境構築

雛形のbin/install-wp-tests.shを下記のように実行します。

$ cd $(wp plugin path --dir my-plugin)
$ bash bin/install-wp-tests.sh wordpress_test root wordpress localhost latest
  • テスト用データベース(ユーザーroot、パスワードwordpress、データベース名wordpress_test)を作成します。
  • /tmpディレクトリへテスト用wordpressなどをインストールします。

※ 既存のデータベースがあるとinstall-wp-tests.shはエラーで終わります。
既存データベース(と既存テスト用wordpress環境)の削除を行った後でinstall-wp-test.shを実行するスクリプトが下記で公開されています。
miya0001/install-wp-test-env

テーマ用テスト環境構築

プラグイン用雛形の中で必要なファイルをテーマディレクトリへコピーし必要な変更を行います。
コピーするファイルはphpunit.xml、tests/bootstrap.phpです。

phpunit.xml

plugin用に作成されたphpunit.xmlをテーマディレクトリへコピーし変更します。

下記サンプルはtest-ではじまるtestsディレクトリのPHPファイルをテストファイルとしテスト対象をincディレクトリとします。

<phpunit
    bootstrap="tests/bootstrap.php"
    backupGlobals="false"
    colors="true"
    convertErrorsToExceptions="true"
    convertNoticesToExceptions="true"
    convertWarningsToExceptions="true"
    >
    <testsuites>
        <testsuite>
            <directory prefix="test-" suffix=".php">./tests/</directory>
        </testsuite>
    </testsuites>
    <filter>
        <whitelist>
            <directory>./inc</directory>
        </whitelist>
    </filter>
</phpunit>

tests/bootstrap.php

plugin用に作成されたbootstrap.phpをテーマディレクトリへコピーしファイルを編集します。
WordPress Theme開発でPHPUnitを使う – Qiitaを参考にしました。

<?php
$_tests_dir = getenv( 'WP_TESTS_DIR' );
if ( ! $_tests_dir ) {
    $_tests_dir = '/tmp/wordpress-tests-lib';
}

require_once $_tests_dir . '/includes/functions.php';

function _manually_load_plugin() {
    register_theme_directory( dirname( __FILE__ ) . '/../../' );
    switch_theme( 'my-theme' );
}

tests_add_filter( 'muplugins_loaded', '_manually_load_plugin' );

require $_tests_dir . '/includes/bootstrap.php';

テストケース作成

テストケースはWP_UnitTestCaseを継承します。

class My_Example_Test extends WP_UnitTestCase {
}

テストのサンプル

<?php
class My_Example1_Test extends WP_UnitTestCase {

    public static function setUpBeforeClass() {
        parent::setUpBeforeClass();
        require_once( dirname( dirname( __FILE__ ) ) . ‘/inc/class.my-example.php’ );
    }

    public function test_do_some() {
        $this->assertTrue( true )
    }
}

functions.phpで下記のように対象クラスを読み込んでいるときはsetUpBeforeClassは必要ありません。(2016.09.20 削除)

<?php
require_once( get_template_directory() . '/inc/class.example1-utils.php' );
require_once( get_template_directory() . '/inc/class.example2-utils.php' );

テスト実行

// テーマディレクトリへ移動
$ cd $(wp theme path --dir my-theme)

// PHPUnit実行
$ phpunit

// カバレッジ作成
$ phpunit --coverage-html ./dev/report

テストのサンプル

inc/class.single-utils.php

<?php
class Single_Utils {
    /**
     * タイトルのプレフィックスへHelloを追加
     *
     * @param string  $prefix  取得対象のアタッチメントID(投稿ID)です。
     * @param boolean $display タイトルを出力するときはtrue、値を返すときはfalseを設定します。
     *
     * @return mixed(void | string) displayがtrueのタイトル文字列を返します。
     */
    public static function custom_single_post_title( $prefix = '', $display = true ) {
        $custom_prefix = $prefix || '';
        single_post_title( 'Hello ' . $custom_prefix, $display );
    }
}
class Single_Utils_Test extends WP_UnitTestCase {
    public static function setUpBeforeClass() {
        parent::setUpBeforeClass();
        require_once( dirname( dirname( __FILE__ ) ) . '/inc/class.single-utils.php' );
    }

    /**
     * @group single
     */
    public function test_custom_single_post_title() {
        $post = $this->factory->post->create_and_get( [
            'post_title' => 'Sample Post',
        ] );

        $this->go_to( '/?p=' . $post->ID );
        $this->assertTrue( is_single() );
        $this->expectOutputString( "Hello Sample Page" );
        Single_Utils::custom_single_post_title();
    }
}

ソース

テストのサンプルです。

固定ページのテストサンプルです。

カテゴリーの汎用的な処理を行うユーティリティークラスとそのテストです。

WordPressのリライトのテストです。

コメント

No comments yet.

コメントの投稿

改行と段落タグは自動で挿入されます。
メールアドレスは表示されません。