DockerでWordPressをPHPUnitで単体テストする | WordPress
前提
- PHP 7.2の場合を想定する
- PHP 7.2系はPHPUnit 9系に対応していない(PHPUnit 9はPHP 7.3以上が必要)ため、PHPUnit 8系を使用する
- PHPUnitおよびYoast / PHPUnit-PolyfillsをComposerでインストールする
/var/www/htmlにWordPressをインストールしたと仮定して進める- WP-CLIを使ってテーマの単体テストの雛形を作成する
docker-compose.yml
WordPressのテスト環境を以下のように設定する。
test_db:
image: mysql:5.7
platform: linux/amd64
container_name: test_db
restart: always
environment:
MYSQL_ROOT_PASSWORD: wordpress_test
MYSQL_DATABASE: wordpress_test
MYSQL_USER: wordpress_test
MYSQL_PASSWORD: wordpress_test
Composerをインストール
# Install Composer for PHPUnit
RUN php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" \
&& php -r "if (hash_file('sha384', 'composer-setup.php') === file_get_contents('https://composer.github.io/installer.sig')) { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;" \
&& php composer-setup.php \
&& php -r "unlink('composer-setup.php');" \
&& chmod u+x composer.phar \
&& mv composer.phar /usr/local/bin/composer
※ 元のコードはComposerインストーラーの検証ハッシュ値を文字列としてハードコードしていたが、このハッシュ値はComposer側のインストーラー更新にともなって変わるため、ハードコードすると将来的に「Installer corrupt」の誤判定を起こす可能性がある。公式ダウンロードページが案内している、https://composer.github.io/installer.sigから最新のハッシュ値を都度取得して比較する方法に修正した。
PHPUnitおよびYoast / PHPUnit-Polyfillsをインストール
Yoast / PHPUnit-Polyfillsは、WordPressの単体テストで必要になる。
composer.json
{
"autoload-dev": {
"psr-4": {
"MyTheme\\Tests\\": "wp-content/themes/my-theme/tests/"
}
},
"require-dev": {
"phpunit/phpunit": "^8.0",
"yoast/phpunit-polyfills": "^2.0"
}
}
Dockerfile
composer.jsonをコンテナにコピーする。
# Install PHPUnit & PHPUnit Polyfills
COPY ./composer.json /var/www/html/composer.json
RUN cd /var/www/html \
&& env COMPOSER_ALLOW_SUPERUSER=1 composer install \
&& composer dump-autoload
※ 元のコードはcd wpとなっていたが、直前でcomposer.jsonをコピーしている先は/var/www/htmlなので、cd /var/www/htmlに修正した。
phpunit.xml.dist
テーマディレクトリ(例: my-theme)にphpunit.xml.distを作成する。
<?xml version="1.0"?>
<phpunit
bootstrap="tests/bootstrap.php"
backupGlobals="false"
colors="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
>
<php>
<const name="WP_TESTS_PHPUNIT_POLYFILLS_PATH" value="/var/www/html/vendor/yoast/phpunit-polyfills"/>
</php>
<testsuites>
<testsuite name="testing">
<directory prefix="test-" suffix=".php">./tests/</directory>
</testsuite>
</testsuites>
</phpunit>
参考
WP-CLIを使用してユニットテストをセットアップ
コンテナ内でwp scaffold theme-testsコマンドを発行する。
container$ cd /var/www/html/wp-content/themes
container$ wp scaffold theme-tests my-theme
my-themeディレクトリにbin/install-wp-tests.shが作成される。
bin/install-wp-tests.shを実行
コンテナ内で実行する。
container$ cd /var/www/html/wp-content/themes/my-theme
container$ bin/install-wp-tests.sh wordpress_test wordpress_test wordpress_test test_db
テスト実行
container$ ../../../vendor/bin/phpunit
サンプル
<?php
/**
* WP_UnitTestCaseのサンプル
*
* @package MyTheme
*/
class Sample_Test extends WP_UnitTestCase {
/**
* 単一ページテスト
*
* @link http://qiita.com/miya0001/items/8f1a777b455a8bdcbd62
*/
public function test_the_title() {
$post = $this->post_ids = $this->factory->post->create_and_get( array(
'post_title' => 'Sample Post!',
) );
$this->go_to( '/?p=' . $post->ID );
$this->assertTrue( is_single() );
$this->expectOutputString( 'Sample Post!' );
the_title();
}
/**
* アーカイブテスト
*/
public function test_single_cat_title() {
$cat = $this->factory->category->create_and_get( array( 'name' => 'Sample Category' ) );
$this->factory->post->create( array( 'post_category' => array( $cat->term_id ) ) );
$this->go_to( '/?cat=' . $cat->term_id );
$this->assertTrue( is_archive() );
$this->assertFalse( is_single() );
$this->expectOutputString( 'Sample Category' );
single_cat_title();
}
}
※ サンプルコードのPHPDocに含まれていた実在の個人名・メールアドレス・パッケージ名は、汎用的なプレースホルダーに置き換えた。