LoginSignup
7
5

More than 5 years have passed since last update.

PHPUnitのtestWithアノテーションを使ってみる

Last updated at Posted at 2017-01-28

プロジェクトのPHPUnitが古く、バージョンを上げようと思った。
最近の変更点を見ていたらtestWithアノテーションというのが4.8から増えたことに気づく。
便利そうなので使おうと思ったががパッと見でドキュメントが見当たらなかったのでメモを残す。

(2018/07/31追記) 
いつのまにかドキュメントが増えていた。
2. アノテーション@testWith

環境

Installing phpunit/phpunit (5.7.8)

PHP 7.1.0 (cli) (built: Jan  3 2017 15:32:50) ( NTS )
Copyright (c) 1997-2016 The PHP Group
Zend Engine v3.1.0-dev, Copyright (c) 1998-2016 Zend Technologies
    with Zend OPcache v7.1.0, Copyright (c) 1999-2016, by Zend Technologies
    with Xdebug v2.5.0, Copyright (c) 2002-2016, by Derick Rethans

結論

json形式で指定しましょう。
連想配列だけちょっと特殊だから気をつける。

とりあえず使ってみる

数値

    /**
     * @testWith [1, 2, 3]
     *           [1.1, 2.2, 3.3]
     */
    public function testNum($a, $b, $expected)
    {
        $this->assertEquals($expected, $a + $b);
    }

文字列

    /**
     * @testWith ["a", "b", "ab"]
     */
    public function testStr($a, $b, $expected)
    {
        $this->assertEquals($expected, $a . $b);
    }

配列

    /**
     * @testWith [["a"], ["b"], ["a","b"]]
     */
    public function testAry($a, $b, $expected)
    {
        $this->assertEquals($expected, array_merge($a, $b));
    }

ここまでは想定内。

連想配列

    /**
     * @testWith [["a"=>1], ["b"=>2], ["a"=>1,"b"=>2]]
     */
    public function testHash($a, $b, $expected)
    {
        $this->assertEquals($expected, array_merge($a, $b));
    }

配列までのノリで出来るかと思ったらテスト始まらなかったので指定の仕方おかしいんだろうということでソースを確認。

Test.php#L511
if (preg_match(self::REGEX_TEST_WITH, $docComment, $matches, PREG_OFFSET_CAPTURE)) {
    $offset            = strlen($matches[0][0]) + $matches[0][1];
    $annotationContent = substr($docComment, $offset);
    $data              = [];
    foreach (explode("\n", $annotationContent) as $candidateRow) {
        $candidateRow = trim($candidateRow);
        if ($candidateRow[0] !== '[') {
            break;
        }
        $dataSet = json_decode($candidateRow, true);
        if (json_last_error() != JSON_ERROR_NONE) {
            throw new PHPUnit_Framework_Exception(
                'The dataset for the @testWith annotation cannot be parsed: ' . json_last_error_msg()
            );
        }
        $data[] = $dataSet;
    }
    if (!$data) {
        throw new PHPUnit_Framework_Exception('The dataset for the @testWith annotation cannot be parsed.');
    }
    return $data;
}

引用元:
https://github.com/sebastianbergmann/phpunit/blob/5.7/src/Util/Test.php#L511

うん、めっちゃjson_decodeしている。
よって連想配列を指定したい場合は下記のようになる。

    /**
     * @testWith [{"a": 1}, {"b": 2}, {"a": 1, "b": 2}]
     */
    public function testHash($a, $b, $expected)
    {
        $this->assertEquals($expected, array_merge($a, $b));
    }

まとめ

一通り指定は出来るのでよっぽど無い限り簡単なテストはtestWithアノテーションでいいのかなと思ったり。
色々やりたいぞいってなったら普段どおりdataProviderアノテーションで頑張る感じで!

動くサンプル

参考

PHPUnit の各バージョンについて調べてみた
Annotation @testWith not documented

2018/03/13 ドキュメントが追加されてることに気付いたが連想配列周りの罠に関しては未記載っぽい
2. アノテーション@testWith

7
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
5