darudaru

だるだるしてるエンジニア

PHPUnitの知らなかったアノテーション

アノテーションとはメソッドのコメント部分に書く@で始まるタグのこと。

/**
 * @アノテーション名 引数
 */

こう使う。
PHPUnitでテストコードを書くことが多いのですが、最近アノテーションの存在を知り、これは便利だなと思ったという話。

いいなと思ったアノテーション

  • 先にやっておくべきテストを実行する
  • 複数パターンのデータをまるっと渡す
  • テストを分類し、特定のテストだけ実行できる

@depends

先にやっておかなきゃいけないテストを指定できる。@depends ファンクション名と書くと、先に指定したテストを実行してからテストを実行してくれる。

<?php

class HogeTest extends \PHPUnit_Framework_TestCase
{
    public function testFirst()
    {
        $this->assertTrue(true);
    }

    /**
     * @depends testFirst 
     */
    public function testSecond()
    {
        $this->assertTrue(false);
    }
}

上の例だと、testSecond()の前にtestFirst()を実行する。
そもそも依存関係があるならリファクタリングすべきでは?というところもありますが、そうは言っても無理な時もあるもんね、という気持ちをわかってくれている機能。ありがたい。

@dataProvider

複数パターンのデータをまとめて渡せる。returnでテストしたデータを返すメソッドを作っておき、データを使いたいテストのメソッドで@dataProvider メソッド名と指定して使う。テストのメソッドでは、引数を指定してデータを受け取れるようにしておけばいい。

<?php

class HogeTest extends \PHPUnit_Framework_TestCase
{

    /**
     * @dataProvider providerHoge
     */
    public function testHoge($param, $expected)
    {
        $this->assertEquals($expected, $param[0] + $param[1]);
    }


    public function providerHoge()
    {
        return array(
            'add 1 and 2' => array( array(1,2), 3),
            'add 5 and 5' => array( array(5,5), 10),
            'add 10 and 2' => array( array(10,2), 12),
            'add 3 and 2' => array( array(3,2), 5),
        );
    }
}

複数のデータのパターンでテストをしたいとき、例えばforeachとかでデータをぐるぐる回してassert関数を実行するような、複数パターン用のコードを書かなくてもいい。テストコードも削れて綺麗にかけます。
データの指定には連想配列が使えるので、各データがどういったパターンのものかをキーで書いておくことでテスト内容も分かりやすくなる。

@group

テストをグループ化してくれる。@group グループ名称で指定する。

<?php
class HogeTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @group hoge
     */
    public function testHoge()
    {
        $this->assertTrue(true);
    }
}

コマンドラインでテストを実行するときに、--groupでグループ名を指定すると、そのグループ名称で定義されているテストを実行してくれる。
便利だと思ったが、まだ実際に使ったことはないです。テストの規模が大きくなってきたら、テストの実行時間を短縮させるために使ったりするとよさげだと思いました。

番外編 @test

testXXXというメソッド名じゃなくても、@testのアノテーションをつけるだけでテストメソッドだと指定できる。

<?php

class HogeTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @test
     */
    public function hoge()
    {
        $this->assertTrue(true);
    }
}

たまに日本語でメソッド名を記述しているテストコードがあるけど、そういったときに使うと見た目が良くなりそう。

ちなみに、日本語でメソッド名書くということが違和感があるかもしれないけど、テスト内容がパッと見るだけでわかるので、いいなと思っています。
Behatだと完全に日本語で書けたりしますが、それはそれで書きづらいし見辛い。エンジニアじゃない人が読むには分かりやすいと思うんだけど、処理はプログラムで書いた方が分かりやすいし早く書けるなと。
なのでテストコードのメソッド名を日本語で簡潔に書いておいてくれるぐらいが、自分にはちょうどいい。

まとめ

アノテーションは、たまたま見ていたテストコードに書かれているのを見つけて知りました。なんだこれ!と思って公式ドキュメント見たら、チュートリアルぐらいのところにほとんど書いてある内容だった。公式ドキュメントにもっと早く目を通して置くべきだと思って反省しました。