phpunit에서 작성한 테스트 케이스를 기반으로 테스트 항목 테이블 작성 - 2

10841 단어 PHPUnitPHP

하고 싶은 일



이전 phpunit에서 작성한 테스트 케이스를 기반으로 테스트 항목 테이블 작성에서 테스트 케이스에서 테스트 내용을 출력하는 곳까지 만들 수있었습니다.

단, 다음과 같은 불만이 있습니다.
  • 명령을 두 번 실행하지 않으면 테스트 테이블이 출력되지 않습니다.
  • 테스트 한 클래스 전부의 결과가 하나로 리포트에 정리되어 버리므로 개별의 테스트 클래스마다의 결과도 보존해 두고 싶다.
  • ※ 제품의 리포지토리와는 다른 리포지토리에 관리하기 쉬운 형태라고 기쁘다


  • 그래서 이번에는 PHPUnit의 테스트 러너의 확장하여 시험 후에 실행하는 처리를 추가해 나가겠습니다.

    처리의 전체 이미지



    이미지로서는 PHPUnit의 테스트 러너로 실행된 테스트 클래스를 감시해 이하와 같은 간단한 구조를 구현하고 있습니다.


    완성된 시험 결과는 이런 느낌으로 우선 배치하려고 합니다.


    구현 방법



    테스트 러너 확장을 위한 클래스 준비



    phpunit 실행 중에 처리를 끼우기위한 테스트 러너 확장 클래스를 준비합니다.
    이번에는 다음과 같은 파일을 배치합니다. 배치 장소는 어디서나 좋지만 이번에는 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>
    

    좋은 웹페이지 즐겨찾기