以前に書いた「XAMPP環境でphpunitをインストールしてユニットテストを実行する」の記事の続編である。

いやはや…最近、公開しているプラグインの機能が増えて来たこともあってか、ビルドバージョンのアップだけなのに、作業コストがかなり増大して来た。それもこれも、テスト項目が多すぎて人力試験では手が回らなくなって来たのが原因だ。そのために、試験してるのに品質が上がらず、リリースしてもバグが潰し切れてないということが目立つようになって来た。さすがに、もう一人で試験していても効率が悪くなる一方だ──という判断から、phpunitでのユニットテストを導入することにした次第。

昨年、WordCampでWordPressコアの開発に参加した際、WordPress環境でphpunit使ってユニットテストしていたので、その時の手順を思い返しながら、Windows(XAMPP)環境下に、WP-CLIとphpunitを入れてプラグインのテスト環境を構築してみた(いやぁ、WordCamp参加してて本当に良かった…)。

ただし、最初に結論を書いておくが、Windows環境でWordPress+phpunitの試験環境を構築するのは凄まじく大変である。まさに茨の道…というか修羅の道に近い(笑)。私も途中で何度か諦めかけたので、素直にVCCWに頼った方が良いだろう。

この記事はその修羅の道を歩みたいというM的気質の方向けの道しるべとして残しておこう。

Windows(XAMPP)環境にWP-CLIをインストールする

WP-CLIはコマンドラインからWordPressを操作できるようになるツールである。これを使うとWordPressの本体を含め、プラグインやテーマのインストールやらアップデートなどおよそWordPress環境関連の開発や制御が驚くほど簡単にできるようになる。基本的にコマンドラインからwp --[option]のようにして利用できるのも便利なところだ。
ただ、このツールはWindowsには限定的にしか対応しておらず、公式サイトでもWindows環境へのインストール方法が紹介されていない。私の開発環境はWindowsなので、まずはそこを克服する必要がある。

まず、本体がないと始まらないので、WP-CLIの公式サイトからwp-cli.pharをダウンロードし、ダウンロードした.pharファイルはXAMPPのPHP実行環境(一般的にはC:\xampp\php)に置く。

その後、同じディレクトリパスにwp.cmdを作成して、ファイル内に下記のように記述する。

@php "%~dp0wp-cli.phar" %*

この辺はXAMPPにphpunitをインストールする方法と同じである。XAMPPのPHPへのパスの通し方などは「XAMPP環境でphpunitをインストールしてユニットテストを実行する」の記事を参照してほしい。
さて、これでWP-CLIが晴れてWindowsのXAMPP環境にインストールされたことになる。さっそくコマンドラインからwpコマンドを発行してみよう。

> wp --info
PHP binary:     C:\xampp\php\php.exe
PHP version:    5.6.14
php.ini used:   C:\xampp\php\php.ini
WP-CLI root dir:        phar://wp-cli.phar
WP-CLI global config:
WP-CLI project config:
WP-CLI version: 0.22.0

──というように表示されれば動作確認はOKだ。

プラグイン試験用のWordPress環境をWP-CLIで作る

ここからがカオスな領域だ。私も七転八倒した感じなので、もし実際にこの道を歩みたいと思っている方はまず一度この章を最後まで読み切ってから、自分なりのベストプラクティスを考えながら実施することをおススメする。

WP-CLIでWordPress環境構築

まず、phpunitでユニットテストを行うプラグイン用のWordPress環境はテスト専用として独立させておいた方が良いだろう。ということで、XAMPPのドキュメントルート上にテスト専用のディレクトリを作成し、そこにテスト用のWordPressをインストールすることにした。

> cd c:\xampp\htdocs
> mkdir test.wordpress
> cd test.wordpress
> wp core download
Downloading WordPress 4.4.2 (en_US)...
Success: WordPress downloaded.
> wp core config --dbname=wp_unittest --dbuser=root
Success: Generated wp-config.php file.
> mysql -u root
MariaDB [(none)]> create database wp_unittest;
Query OK, 1 row affected (0.03 sec)
MariaDB [(none)]> exit
Bye
> wp core install --url=localhost/test.wordpress --title=for_test --admin_user=admin --admin_password=password --admin_email=***@***
Success: WordPress installed successfully.
> wp scaffold plugin for-unittest-plugin --path=`c:\xampp\htdocs\test.wordpress`
Success: Created plugin files.
Success: Created test files.
> cd $(wp plugin path for-unittest-plugin --dir)

これで、XAMPPのドキュメントルート(一般的にc:\xampp\htdocs)直下のtest.wordpressフォルダ内にテスト用のWordPressがインストールされ、そのWordPress内にユニットテスト用の「for-unittest-plugin」というプラグインのひな形が登録される。
最後のcdは指定したプラグインのディレクトリ直下に移動するためのコマンドだ。

Cygwin編 ─ バッドエンド

次に、プラグインを試験するためのWordPress環境を作ってあげる必要がある。これがないと、プラグイン内のソースでWordPressに依存している部分(ファイルパスやテンプレート関数など)がエラーになってユニットテストどころではないのだ。実際、上記のコマンドの後でphpunitコマンドでユニットテストを実行してみると、WordPressで定義される定数がないというエラーが出る。
そんなわけで、ユニットテスト用のWordPress実行環境を構築したいのだが、いかんせん、ユニットテスト用のWordPress環境を構築するためのシェルファイル(WP-CLIのwp scaffold pluginコマンドで作成されたプラグインのひな形フォルダ内のbin/install-wp-tests.sh)がWindows環境では動かせない。Gitのクライアントを入れているとWindowsのコマンドプロンプトでもbashが使えるのだが、シェルファイルのパスを通してあげても正常に動作しなかった。
そこで、Windows上にUNIX(Linux)環境を構築するためにCygwinをインストールすることにした。

やってから後悔したが、この時点でXAMPP使っている意味がなくなるのでCygwinへの道はオススメしない…。

Cygwinのインストールだが、まずはCygwinの公式サイトから、利用しているWindowsOSの種別(32bitか64bit)に合わせてEXEファイルをダウンロードする。ダウンロードしたEXEファイルを開けばインストーラーが起動するので、後はインストーラーの手順に沿って進めればよい…そう、それでよい…ような気がしたんだが、覚悟してほしい。インストールには個々のネットワーク環境にもよるが、10時間以上かかる。私の場合、昼の14時に開始して、24時の時点でも終わってなかった(ダウンロードは終わっていたが、インストール中で40%ぐらいの進捗率だった)。そんなわけで、この道を選んだ方はその日の作業継続はあきらめて寝てしまおう(なんちゅー手順だ…)。

さて、次の日になるとおそらくCygwinのインストールが終わっている(笑)。
これでbashコマンドが実行できるようになっているので、install-wp-tests.shをテキストエディッターで開いて、bashのパスをCygwin側に通してあげる必要がある。Cygwinの実行パスは私の場合64ビットOS版だったので、C:\cygwin64\binだった。なのでシェルファイルの1行目のshebangを次のように書き換える。

#!/cygwin64/bin/ bash

では、さっそくCygwinのターミナルを起動して、install-wp-tests.shを実行してみよう。なぜかWordPressのバージョン指定でlatestにすると見つからないと怒られたので、nightlyでやってみた。

$ cd /cygdrive/c/xampp/htdocs/test.wordpress/wp-content/plugins/for-unittest-plugin
$ bash bin/install-wp-tests.sh wordpress_test root '' localhost nightly
$ bash bin/install-wp-tests.sh wordpress_test root '' localhost nightly
$ bash bin/install-wp-tests.sh wordpress_test root '' localhost nightly

なぜ3回同じコマンドを実行しているかというと、なぜかシェル内で関数化されている各プロセス(install_wpinstall_test_suiteinstall_db)が連続で実行されないからだ。おそらくCygwin側にWP-CLIがインストールされていないため、内部でWP-CLIに依存している処理があって、そこでエラーになって終了されてしまうのかもしれない(よくわからん)。まぁ、bash実行する前にCygwinにWP-CLIをインストールすれば解決するのだろうが、PHPからインストールしないといかんのでさすがにそれはパスした。
もしCygwin+WP-CLIの環境構築というもう一つの修羅の道を歩みたい方は、下記のページを道しるべにしてみると良いだろう。

【Windows 編】Cygwin を使用して WP-CLI をインストールする
Mao PC エンジニア

3回目のシェル実行後、

+ mysqladmin create wordpress_test --user=root --password= --host=localhost --protocol=tcp

──と表示されれば、普通はユニットテスト用のWordPressの実装は完了なのだが…Windows環境ではこのままではダメだ。まず、Cygwin経由のbashで展開されるtmp/フォルダがシステムルートにないので、移動してあげる必要がある。

$ mv /cygdrive/c/cygwin64/tmp /cygdrive/c/.

これでC:\tmp\の下にユニットテスト用のWordPressが準備できた。しかし、C:\tmp\wordpress\の中身を見てみて欲しい。何も入っていないハズだ。そう、Cygwinでのシェルスクリプト実行ではダウンロードが軒並み失敗している。私の場合、svnリポジトリからのダウンロードは成功していたが、もしもsvnがWindowsにインストールされていない場合はそっちもコケていて、フォルダの中身はすべて空っぽかもしれない…。

Windows環境ではひな形に同梱されているシェルスクリプトではテスト環境構築をする場合には、Cygwin+WP-CLI環境が必要ということになるのかもしれない(試してないので何とも言えないが)。今さらXAMPPでインストール済みのPHPやらMySQL、それに今回既にインストールしたWP-CLIをさらにCygwin用にインストールし直すのはこの記事の(XAMPPで…という)主旨にマッチしないので却下だ。そんなわけで、このルートは私的にはバッドエンドということで封印することにした(涙)

手動編 ─ トゥルーエンド!?

気を取り直して、一番やりたくなかった原始的な方法に頼ることにした。つまりは、install-wp-tests.shのシェルスクリプトで実行されるコマンドを手動でやって行く──ということだ。あぁ、まさに修羅の道…。WP-CLIがインストール済みなのが唯一の救いである。

Cygwin編をやっているといくつかのコマンドは不要になるが、ここではCygwinなんぞないモノとしてシェルスクリプトで実行されるコマンドをすべて順に実行していく。私はPowerShell使いなので、下記コマンドはPS準拠である。

1. ダウンロード ~ インストール

シェルスクリプトでいうところのdownload()install_wp()の部分だ。

> cd /
> mkdir -p /tmp/wordpress
> mkdir -p /tmp/wordpress-nightly
> (new-object System.Net.WebClient).Downloadfile("https://wordpress.org/nightly-builds/wordpress-latest.zip", "/tmp/wordpress-nightly/wordpress-nightly.zip")
> unzip -q /tmp/wordpress-nightly/wordpress-nightly.zip -d /tmp/wordpress-nightly/
> mv /tmp/wordpress-nightly/wordpress/* /tmp/wordpress/
> (new-object System.Net.WebClient).Downloadfile("https://raw.github.com/markoheijnen/wp-mysqli/master/db.php", "/tmp/wordpress/wp-content/db.php")

ファイルのダウンロードコマンドについては私はPowerShell組込みのコマンドでやったが、もしwget使えるならば-Oオプション付きでやっても問題ない。

2. テストライブラリのインストール

シェルスクリプトでいうところのinstall_test_suite()の部分だ。要SVNインストール済みのこと。WindowsへのSVNインストールは過去に書いた「Windows PCユーザー向け WordPressコア修正環境の構築手順」を参照してほしい。

> mkdir -p /tmp/wordpress-tests-lib
> svn co --quite https://develop.svn.wordpress.org/trunk/tests/phpunit/includes/ /tmp/wordpress-tests-lib/includes

もし、コマンドラインでsvnコマンドが使えない場合、作成した/tmp/wordpress-tests-libフォルダ内でGUIから右クリックしてチェックアウトしても良い(下図参照)。

SVN Checkout
> cd /tmp/wordpress-tests-lib
> (new-object System.Net.WebClient).Downloadfile("https://develop.svn.wordpress.org/trunk/wp-tests-config-sample.php", "/tmp/wordpress-tests-lib/wp-tests-config.php")

ここからはsedコマンドが使えるかどうかで手順が分かれる(Windows版のGitをインストールしているとsedが使える)。とりあえずはコマンドラインでsed --versionを実行してエラーにならないか確認してみて欲しい。sedが利用可能なら、引き続きコマンドラインで下記コマンドを実行していく。

> sed -i "s:dirname( __FILE__ ) . '/src/':'/tmp/wordpress/':" C:\tmp\wordpress-tests-lib\wp-tests-config.php
> sed -i "s/youremptytestdbnamehere/wordpress_test/" C:\tmp\wordpress-tests-lib\wp-tests-config.php
> sed -i "s/yourusernamehere/root/" C:\tmp\wordpress-tests-lib\wp-tests-config.php
> sed -i "s/yourpasswordhere//" C:\tmp\wordpress-tests-lib\wp-tests-config.php
> sed -i "s|localhost|localhost|" C:\tmp\wordpress-tests-lib\wp-tests-config.php

もしsedコマンド実行時にパーミッションエラーが出る場合は、別途、管理者権限でPowerShellを開いて実行すれば問題ない。

sedコマンドを使わずに設定を変更する場合は、直接C:\tmp\wordpress-tests-lib\wp-tests-config.phpをGUI側から開いてファイルを編集することになる。

/* Path to the WordPress codebase you'd like to test. Add a forward slash in the end. */
define( 'ABSPATH', '/tmp/wordpress/' );

(中略)

define( 'DB_NAME', 'wordpress_test' );
define( 'DB_USER', 'root' );
define( 'DB_PASSWORD', '' );
define( 'DB_HOST', 'localhost' );
define( 'DB_CHARSET', 'utf8mb4' );
define( 'DB_COLLATE', '' );

(省略)

上記のように設定を書き換えればOKだ。

3. テスト用データベースの準備

シェルスクリプトでいうところのinstall_db()の部分だ。

> mysqladmin create wordpress_test --user=root --host=localhost --protocol=tcp

これで完了だ。

phpunitを実行してみる

長い道のりの末、ようやくWindows(XAMPP)環境でのWordPress+phpunitによるテスト環境の準備ができたので、早速プラグインのユニットテストを試してみよう。

> cd C:\xampp\htdocs\test.wordpress\wp-content\plugins\for-unittest-plugin
> phpunit
Installing...
Running as single site... To run multisite, use -c tests/phpunit/multisite.xml
Not running ajax tests. To execute these, use --group ajax.
Not running ms-files tests. To execute these, use --group ms-files.
Not running external-http tests. To execute these, use --group external-http.
PHPUnit 5.0.10 by Sebastian Bergmann and contributors.

.                                                                  1 / 1 (100%)

Time: 5.7 seconds, Memory: 22.25Mb

OK (1 test, 1 assertion)

やっと動いた…感無量だ(T△T)

WordPressの開発って、ホント、Windowsユーザーに過酷な道を強いるわぁ…素直にMACで開発するのが一番なのかもしれない。