WordPressでユニットテスト。管理画面上でphpunit実行

WordPressでPHPUnitを使ってユニットテストする方法です。
WordPressのカスタマイズはある程度の経験があるが、テストは書いたことが無い、という方を想定しています。
WordPressのショートコードの実行結果をテストしてみます。ショートコードについては、[WordPress ショートコードの作成方法](https://ounziw.com/2018/03/16/wordpress-shortcode/) を参照。

## ユニットテストとは
ユニットテストとは、プログラムが正しく記述されているかどうかを確認する手法の一つです。「実際にコードを実行した結果」と「プログラムが想定する結果」を比べる作業を行います。この作業を実行するコードをテストコードと呼びます。

プログラムが正しく記述されているかどうかを確認する方法としては、

「実際にプログラムを実行した結果を目視して動作確認する」

という方法がまず思い浮かびますね。しかし、この方式だと、頻繁にテストするのは大変です。また、もしバグが発生した場合に、バグの原因の箇所がすぐ特定できないかもしれません。

これでは困りますね。そうならないためには、

■ テストを実行する手間が少ない
■ テストが失敗した場合、どこで失敗したかが分かる

が大事ですね。これらをやってくれるのが、PHPUnitです。[^1]

## WordPressで手軽にPHPUnitを使う方法
はじめてユニットテストする、という人を想定して、環境構築が楽であろう方法を紹介します。方法は、

1. WordPressにwp-unitプラグインをインストールする。以上

と、とても簡単です。ただしwp-unitプラグインは実運用サイトで使うものではないので、テスト用のWordPressで行うことを推奨します。

ちなみに本格的にPHPUnitを使う方法は[こちら](https://make.wordpress.org/core/handbook/testing/automated-testing/phpunit/) に記載されています。

## テストコードを書いてみる
では実際にテストコードを書いてみましょう。

    <?php
    class SCTest extends PHPUnit_Framework_TestCase {

        function testshortcode(){
            $output = do_shortcode('[mymitsu]https://my-mitsu.jp/estimation/292[/mymitsu]');
            $expected = '<iframe src="https://my-mitsu.jp/estimation/292" id="mymitsu" width="640" height="480"></iframe>';
            $this->assertEquals($expected, $output);
        }
    }

PHPUnitでは、テストケースは、クラスPHPUnit_Framework_TestCaseを継承したクラスにします。[^2] クラスSCTestは、自分で好きな名前を付けれますが、Testを含めた名前にするのが通例のようです。ショートコード(ShortCode)のテストなので、SCTestにしました。

    $this->assertEquals($expected, $output);

の部分が、テストを実行している箇所で、\$output(=実行結果)と\$expected(=期待される結果)が同じならテスト成功、同じでなければテスト失敗、となります。\$outputと\$expectedに設定されているデータは、それぞれ、

            $output = do_shortcode('[mymitsu]https://my-mitsu.jp/estimation/292[/mymitsu]');

\$outputは、ショートコードを実行した結果を格納しています。

            $expected = '<iframe src="https://my-mitsu.jp/estimation/292" id="mymitsu" width="640" height="480"></iframe>';

\$expectedは、「iframeを出力するhtml」です。

なお、この例では、プラグイン[Shortcode for My Mitsu Estimation Form](https://ja.wordpress.org/plugins/shortcode-for-my-mitsu-estimation-form/)のショートコードをテストしています。

テストは、\$output(ショートコードを実行した結果)が、\$expected(iframeを出力するhtml)と同じであれば成功、となります。

## テストの実行
wp-unitをインストールすると、管理画面からテストを実行できます。

![wp-unitでテスト実行](https://qiita-image-store.s3.amazonaws.com/0/31643/b858e698-230c-d3d0-225c-330d40ef365e.png)

テストを実行するには、画面上の**Run**ボタンを押すだけです。上の画像はテスト成功の場合ですが、もしテストが失敗した場合は、どのテストが失敗したかが表示されます。こうすることで、

■ テストを実行する手間が少ない
■ テストが失敗した場合、どこで失敗したかが分かる

が実現されているわけです。

## 書いてみたテストの例

    <?php
    class SCTest extends PHPUnit_Framework_TestCase {
        function testshortcode(){
            $output = do_shortcode('[mymitsu]');
            $expected = '<iframe src="https://my-mitsu.jp/estimation/274" id="mymitsu" width="640" height="480"></iframe>';
            $this->assertEquals($expected, $output);

            $output = do_shortcode('[mymitsu id="myid" width="480" height="360"]');
            $expected = '<iframe src="https://my-mitsu.jp/estimation/274" id="myid" width="480" height="360"></iframe>';
            $this->assertEquals($expected, $output);

            $output = do_shortcode('[mymitsu]292[/mymitsu]');
            $expected = '<iframe src="https://my-mitsu.jp/estimation/292" id="mymitsu" width="640" height="480"></iframe>';
            $this->assertEquals($expected, $output);
        }
    }

上の例は、比較的単純なテスト例です。ショートコードとその属性値の実行チェックです。ショートコードを実際に投稿本文中に書いて動作確認するよりも、テストコードを書いて、**Run**ボタンを押すほうが楽でしょう。動作確認が一回だけなら、余り変わらないかもしれませんが、プログラム更新のたびに動作確認する、と考えると、テストコードを書いたほうが楽だと思います。

少し複雑な例も記載しておきます。

    <?php
    class SCAttsFilterTest extends PHPUnit_Framework_TestCase {
        function setfilter ( $atts ) {
            $ratio = 0.75;
            $atts["width"] *= $ratio;
            $atts["height"] *= $ratio;
            return $atts;
        }

        function setUp(){
            add_filter('shortcode_atts_mymitsu', array( $this, 'setfilter'));
        }

        function testshortcode(){
            $output = do_shortcode('[mymitsu]');
            $expected = '<iframe src="https://my-mitsu.jp/estimation/274" id="mymitsu" width="480" height="360"></iframe>';
            $this->assertEquals($expected, $output);

            $output = do_shortcode('[mymitsu width="640"]');
            $expected = '<iframe src="https://my-mitsu.jp/estimation/274" id="mymitsu" width="480" height="360"></iframe>';
            $this->assertEquals($expected, $output);
        }

        function tearDown() {
            remove_filter('shortcode_atts_mymitsu', array( $this, 'setfilter'));
        }
    }

setUp()は、テストの前に実行する処理を書きます。tearDown()は、テストの後に実行する処理を書きます。この例では、setUp()でフィルターフック追加、tearDown()でフィルターフック除去、を行っています。このようにすることで、フィルターフックで処理を追加した場合のテストも行うことが可能です。

もちろん、

        function testshortcode(){
            add_filter('shortcode_atts_mymitsu', array( $this, 'setfilter'));
            ...
            テストコード
            ...
            remove_filter('shortcode_atts_mymitsu', array( $this, 'setfilter'));
        }

と書くこともできますが、setUp()、tearDown()を使ったほうが読みやすくなると思います。


[^1]: 昔に書いた記事[WordPressでユニットテスト](http://ounziw.com/2011/09/13/unittest/)では、PHPUnitの他にもSimpleTest、limeを紹介しました。2011年の記事なので、その頃はまだユニットテストの定番ツールが決まっていなかったのでしょう。今ならPHPUnitを選べば良いでしょうから、PHPUnitを活用します。

[^2]: WordPressでは、テスト用のクラスWP_UnitTestCaseが用意されている。WP_UnitTestCaseを使うと、WordPressに投稿を追加する、WordPressにカテゴリーを追加する、など、WordPressの機能のテストが行いやすいです。ただしwp-unitプラグインは標準ではWP_UnitTestCaseに非対応です。今回はテストを始めよう、という趣旨なので、wp-unitプラグインをセットアップするだけでできるテストに限定しています。