8
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

phpunitで作成したテストケースをもとに試験項目表を作成する

Last updated at Posted at 2019-08-02

目的

私が以前所属していたチームでは

  1. 単体試験表を作成(EXCELなどのドキュメント)
  2. ユニットテストの作成
  3. 実装
  4. テスト実施

という流れで開発を行っていましたが、単体試験の試験表を作成と保守していくコストが掛かるようになり

  1. ユニットコードの作成
  2. 試験項目表の自動生成
  3. 実装
  4. テスト実施

とすることはできないか検討してみました。

手順

phpunit.xmlで試験の結果をjunit形式で出力する

phpunitのマニュアルによるとphpunit.xmlにtype="junit"を指定するとテスト実行時に自動でログを出力してくれるので追記します。
今回はtests配下にlogというフォルダを設けてそちらに出力します。

phpunit.xml
    <logging>
        <log type="junit" target="./tests/log/logfile.xml"/>
    </logging>

試しに実行してみます

vendor/bin/phpunit
PHPUnit 7.5.13 by Sebastian Bergmann and contributors.

...                                                                 3 / 3 (100%)

Time: 1.33 seconds, Memory: 14.00 MB
logfile.xml
<testsuites>
<testsuite name="" tests="3" assertions="3" errors="0" failures="0" skipped="0" time="1.102644">
<testsuite name="Unit" tests="2" assertions="2" errors="0" failures="0" skipped="0" time="0.806409">
<testsuite name="Tests\Unit\Auth\RegisterControllerTest" file="/var/www/html/tests/Unit/Auth/RegisterControllerTest.php" tests="1" assertions="1" errors="0" failures="0" skipped="0" time="0.768928">
<testcase name="testExample" class="Tests\Unit\Auth\RegisterControllerTest" classname="Tests.Unit.Auth.RegisterControllerTest" file="/var/www/html/tests/Unit/Auth/RegisterControllerTest.php" line="16" assertions="1" time="0.768928"/>
</testsuite>
<testsuite name="Tests\Unit\ExampleTest" file="/var/www/html/tests/Unit/ExampleTest.php" tests="1" assertions="1" errors="0" failures="0" skipped="0" time="0.037481">
<testcase name="testBasicTest" class="Tests\Unit\ExampleTest" classname="Tests.Unit.ExampleTest" file="/var/www/html/tests/Unit/ExampleTest.php" line="15" assertions="1" time="0.037481"/>
</testsuite>
</testsuite>
<testsuite name="Feature" tests="1" assertions="1" errors="0" failures="0" skipped="0" time="0.296235">
<testsuite name="Tests\Feature\ExampleTest" file="/var/www/html/tests/Feature/ExampleTest.php" tests="1" assertions="1" errors="0" failures="0" skipped="0" time="0.296235">
<testcase name="testBasicTest" class="Tests\Feature\ExampleTest" classname="Tests.Feature.ExampleTest" file="/var/www/html/tests/Feature/ExampleTest.php" line="15" assertions="1" time="0.296235"/>
</testsuite>
</testsuite>
</testsuite>
</testsuites>

...かなりわかりにくいですがひとまず試験の内容を出力することができました。

見やすい形式に変換する

こちらのXMLTテンプレートをもとにXMLをHTMLに変換するとかなり見やすくなるようですので、変換してみます。

※xsltprocが入っていない場合は以下のコマンドでインストールしてください。

sudo apt-get install xsltproc

こちらがHTML変換用のコマンドです。

xsltproc phpunit.xslt tests/log/logfile.xml > output.html

こちらが出力されたHTMLです、かなり見やすくなったのではないでしょうか。
output_html.png

ただ、そのまま使うだけだとテストケースが出力されないため試験の内容がわかりにくく感じたのでテンプレートの内容を少し修正しました。
2019-08-02_13h03_32.png

修正したphpunit.xsltはこちらにも配置してあるので好きに使ってください。
https://gist.github.com/yamamoto-taku/aa3cf2fe6d498a5a855c0f948a29cecd

実例

sampleとしてlaravelの会員登録フォームのバリデーションについてユニットテストを作成し、どのような感じになるか試してみます。

まず以下のコマンドでlaravelの会員機能一式を作成します。

php artisan make:auth

上記のコマンドで作成された以下の関数を試験するテストコードを作成しようと思います。

RegisterController.php
    /**
     * Get a validator for an incoming registration request.
     *
     * @param  array  $data
     * @return \Illuminate\Contracts\Validation\Validator
     */
    protected function validator(array $data)
    {
        return Validator::make($data, [
            //デフォルトのバリデーションだとひらがなでも登録できるので末尾の正規表現は追記しています。
            'name' => ['required', 'string', 'max:255', 'regex:/^[a-zA-Z0-9-_]+$/'],
            'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
            'password' => ['required', 'string', 'min:8', 'confirmed'],
        ]);
    }
RegisterControllerTest.php

<?php

namespace Tests\Unit\Auth;

use App\Http\Controllers\Auth\RegisterController;
use Tests\TestCase;

class RegisterControllerTest extends TestCase
{
    protected $target;

    /**
     * @return void
     */
    public function setUp(): void
    {
        parent::setUp();
        $this->target = new RegisterController();
    }

    /**
     * @test
     * @throws \ReflectionException
     */
    public function 正常系()
    {
        $method = $this->changeAccessible('validator');

        $input = [
            'name' => 'yamamoto-taku',
            'email' => 'hoge@example.com',
            'password' => 'password',
            'password_confirmation' => 'password',
        ];
        $validator = $method->invoke($this->target, $input);
        $this->assertTrue($validator->passes());
    }

    /**
     * @param array $input
     * @dataProvider validatorProviderForFailure
     * @test
     * @throws \ReflectionException
     */
    public function 異常系(array $input)
    {
        $method = $this->changeAccessible('validator');
        $validator = $method->invoke($this->target, $input);
        $this->assertFalse($validator->passes());
    }

    /**
     * @return array
     */
    public function validatorProviderForFailure()
    {
        $input = [
            'name' => 'あいうえお',
            'email' => 'hoge@example.com',
            'password' => 'password',
            'password_confirmation' => 'password',
        ];
        $null = [
            'name' => null,
            'email' => null,
            'password' => null,
            'password_confirmation' => null,
        ];

        return [
            '必須入力チェック' => [$null],
            '日本語入力ひらがな' => [$input],
        ];
    }


    /**
     * @param $object
     * @return mixed
     * @throws \ReflectionException
     */
    public function changeAccessible($methodName)
    {
        $reflection = new \ReflectionClass($this->target);
        $method = $reflection->getMethod($methodName);
        $method->setAccessible(true);
        return $method;
    }
}

phpunitを実行してHTMLへの変換処理をかけます。

vendor/bin/phpunit tests/Unit/Auth/RegisterControllerTest.php
xsltproc phpunit.xslt tests/log/logfile.xml > output.html

生成された結果がこちらです。
データセットを持つ試験項目はデータラベルで、単一の試験項目については関数名でレビュアーにどのような試験を実施する想定かを伝えることができそうです!
2019-08-02_15h32_51.png

#終わりに
上記のような自動レポートの機能を使って単体試験表を別途書かなくてもOKとなればいいなーと思います。あと変換の処理も合わせて自動でできそうな気もするのでそちらも別途検討してみようと思います。
PHPUnitのテストランナーを拡張して自動化できましたのでつづきを書きました

#参考
PHPUnit のテスト結果を人間に優しい感じで出力する

自動化対象のユニットテスト(単体テスト)の仕様書を書くことは完全なる無駄である

8
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
8
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?