PHPUnitでユニットテスト③ パラメータテストを行う方法

PHPUnitでパラメータテスト

PHPUnitでパラメータテストを行う方法をメモします。

環境: PHPUnit 9.5.4、 PHP 7.4.8

パラメータテストとは

パラメータテスト(パラメタライズドテスト)とはユニットテスト対象のひとつのロジックに対し異なるデータで複数パターンをテストする手法のことで、PHPUnitにはパラメータテストを行うための機能が標準で備わっています。

SAMPLE

テスト対象クラスCalculatorに単純な足し算の結果を返すaddメソッドを実装します。

<?php

namespace app\src;

class Calculator
{
    /**
     * 引数 a, bの足し算の結果を返す
     * @return int
     */
    public function add(int $a, int $b)
    {
        return $a + $b;
    }
}

dataProviderを使用する

テストケースクラスCalculatorTestを用意し、dataProviderというパラメータテストを行うための機能を使用してユニットテストを実装します。

<?php

use PHPUnit\Framework\TestCase;
use app\src\Calculator;

class CalculatorTest extends TestCase
{
    public function add_parameters()
    {
        return [
            [0, 1, 1],
            [1, 1, 2],
            [1, 9, 10],
            [1, 10, 11],
            [10, 10, 20],
            [0, -1, -1],
            [1, -2, -1],
            [-1, 1, 0],
            [-1, -9, -10],
            [-1, -10, -11],
            [-10, -10, 20],
        ];
    }
    
    /**
     * @dataProvider add_parameters
     */
    public function testAdd($input_a, $input_b, $expected)
    {
        $calc = new Calculator();
        $result = $calc->add($input_a, $input_b);

        $this->assertEquals($expected, $result, "足し算の結果が正しくありません");
    }

}

addメソッドのテストメソッドtestAddと、テスト用のデータ(パラメータ)を配列に含んだadd_parametersメソッドを用意します。

testAddメソッドに対して@マークで始まるアノテーション記法、@dataProviderをコメントとして適用し、うしろにadd_parametersメソッドを指定することでadd_parameters内の配列内に用意された要素の数だけテストを繰り返し行うことができるようになります。

add_parametersメソッド内、returnに指定された配列のさらに配列となった要素がひとつのパラメータの組みとなり、例えばひとつめの要素内、0, 1, 1の値が、addメソッドの2つの引数と比較用のアサーションメソッドの期待値の変数expectedに割り当てられます。

(テストの実行結果)

PHPUnit 9.5.4 by Sebastian Bergmann and contributors.

..........F                                                       11 / 11 (100%)

Time: 00:00.039, Memory: 6.00 MB

There was 1 failure:

1) CalculatorTest::testAdd with data set #10 (-10, -10, 20)
足し算の結果が正しくありません
Failed asserting that -20 matches expected 20.

/Users/ken/Sites/phpunit-lesson/app/test/calculator/CalculatorTest.php:33

FAILURES!
Tests: 11, Assertions: 11, Failures: 1.

Failed asserting that -20 matches expected 20.
「期待値として指定した値は 20ですが、実際には-20が返っています。」

11個のテストパターンのうち、ひとつのテストケースの誤りを見つけることが出来ました。

パラメータのパターンに名前をつける

dataProviderによるパラメータテストでは、テストの意図をわかりやすくするために、用意したパラメータに名前をつけて実行することも出来ます。

受け取った引数の数値が偶数である場合、結果にtrueを返すisEvenメソッドを例にテストします。

Number.php

<?php

namespace app\src;

class Number 
{
    /**
     * 受け取った引数が偶数であるか
     * @return bool
     */
    public function isEven(int $number) : bool
    {
        return $number % 2 === 0;
    }

}

テストケースクラス NumberTest.php

<?php
use PHPUnit\Framework\TestCase;
use app\src\Number;

class NumberTest extends TestCase
{
    public function is_even_parameters()
    {
        return [
            '偶数のパラメータ' => [
                'param' => 2, 
                'expected' => true
            ],
            '奇数のパラメータ' => [
                'param' => 1, 
                'expected' => false
            ],
        ];
    }
    
    /**
     * @dataProvider is_even_parameters
     */
    public function testIsEven($param, $expected)
    {
        $number = new Number();
        $result = $number->isEven($param);
        
        $this->assertSame($expected, $result, '偶数の場合に真、奇数の場合に偽となる');
    }
}

最初のテストケースクラスと同様、dataProviderを利用しますが、今回はテストパターンのパラメータの配列の要素に連想配列のキーとして名前を付けています。

※要素の値にもそれぞれparamとexpectedと名前を付けてよりわかりやすくしていますが、こちら必須ではありません。

このようにパラメータの組みに名前をつけることで、テスト実行時にfilterオプションを利用してそのパターンのみのテストを行うことが可能となります。

(例) パターン「偶数のテスト」のみをテストする場合

vendor/bin/phpunit --testsuite Number --filter testIsEven@偶数のパラメータ

filterオプションで、テストメソッド名@パラメータのパターン名 とする

(補足)
アサーションメソッドの第三引数に指定している文字列が、テスト失敗時に詳細として表示されるようになります。
※assertSameに限りません

Follow me!