1
0

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で作成したテストケースをもとに試験項目表を作成する-その2

Posted at

やりたいこと

前回phpunitで作成したテストケースをもとに試験項目表を作成するでテストケースから試験の内容を出力するところまで作成できました。

ただ、以下のような不満があります。

  • コマンドを2回実行しないと試験表が出力されない。
  • テストしたクラス全部の結果が一つにレポートにまとまってしまうので個別のテストクラスごとの結果も保存しておきたい。
    • ※製品のリポジトリとは別のリポジトリに管理しやすい形だと嬉しい

そこで今回はPHPUnitのテストランナーの拡張して試験あとに実行する処理を追加していこうと思います。

処理の全体像

イメージとしてはPHPUnitのテストランナーで実行されたテストクラスを監視して以下のような簡単なしくみを実装しています。
outputPhpunitTest.png

出来上がった試験結果はこんな感じでとりあえず配置しようと思います。
2019-08-21_10h41_05.png

実装方法

テストランナー拡張用のクラスを用意する

phpunitの実行中に処理を挟むためのテストランナー拡張用クラスを用意します。
今回は以下のようなfileを配置します。配置場所はどこでもよいですが今回はtestsフォルダ配下にExtensionフォルダを設けてそちらに格納するようにしました。

BeforeTestHookで実行中のテストクラス名を取得して、処理完了後にHTMLへの変換処理を実行しています。

余談ですがAfterLastTestHookというイベントフックもあったのですが、HTMLへの変換のもとにしているファイル出力がAfterLastTestHookのタイミングではまだ生成されていなかったのでデストラクタでテスト完了後の処理を記述しています。

TestRunnerExtension.php
<?php


namespace Tests\Extension;

use PHPUnit\Runner\BeforeTestHook;

final class TestRunnerExtension implements BeforeTestHook
{
    /**
     * @var string
     */
    private $resultFilePath = 'tests/log/logfile.xml';

    /**
     * @var string
     */
    private $testedFileList = 'tests/log/testedFileList.txt';

    /**
     * @var string
     */
    private $resultDir = 'tests/log/result/';

    /**
     * @var array
     */
    private $classList = [];

    /**
     * PHPUnitのログが出力後にファイル生成を行いたいので
     * __destructで終了処理を記述する。
     */
    public function __destruct()
    {
        if (!file_exists($this->resultFilePath)) {
            return;
        }
        if (count($this->classList) > 1) {
            $this->multiClassTestReport();
        } else {
            $this->singleClassTestReport();
        }
    }

    /**
     * 複数のクラスにまたがって試験した場合は個別のテストクラスも実行する。
     * @throws \ReflectionException
     */
    private function multiClassTestReport()
    {
        exec('xsltproc phpunit.xslt ' . $this->resultFilePath . ' > ' . $this->resultDir . 'output.html');

        if (file_exists($this->testedFileList)) {
            unlink($this->testedFileList);
        }

        foreach ($this->classList as $className) {
            $reflection = new \ReflectionClass($className);
            exec('vendor/bin/phpunit ' . $reflection->getFileName());
        }
    }

    /**
     * 単一のクラスの試験ではクラス名と対応したパスにファイルを生成する。
     */
    private function singleClassTestReport()
    {
        $filePathArr = explode('\\', $this->classList[0]);
        $fileName = array_pop($filePathArr);
        $filePath = implode('/', $filePathArr);

        if (!file_exists($this->resultDir . $filePath)) {
            mkdir($this->resultDir . $filePath, 0777, true);
        }
        exec('xsltproc phpunit.xslt ' . $this->resultFilePath . ' > ' . $this->resultDir . $filePath . '/' . $fileName . '.html');
    }

    /**
     * 実行されたテスト情報からテスト対象のクラス名を取得する。
     * @param string $test
     */
    final public function executeBeforeTest(string $test): void
    {
        $test = substr($test, 0, strpos($test, '::'));
        if (!in_array($test, $this->classList, true)) {
            $this->classList[] = $test;
        }
    }
}

phpunit.xmlに拡張クラスを追記する。

上記で作成した拡張クラスをphpnit.xmlに以下のように追記します。
これでphpunitを実行するだけで拡張クラスに記述した処理を自動で実行してくれます。

phpunit.xml
    <extensions>
        <extension class="Tests\Extension\TestRunnerExtension"/>
    </extensions>
1
0
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
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?