PHPUnit 데이터 제공업체에서 테스트에 필요한 모든 데이터를 프로바이드

6943 단어 PHPUnitPHP라라벨

이 기사에 대하여



PHPUnit을 사용하여 테스트를 작성할 때 각 테스트 케이스마다 데이터 준비 및 어설션이 다를 수 있습니다.
테스트 메소드 자체를 나누는, 라고 하는 방법이라도 괜찮습니다만, 거기까지가 아니구나, 라고 하는 경우에, 그것들을 모두 데이터 프로바이더를 사용해 테스트 메소드에 건네주면 좋지 않다,라고 생각했다 그래서 해 보았습니다.

소개



PHPUnit을 사용한 테스트에는 크게 나누어 다음이 필요합니다.
  • 이전 준비
  • 입력 파라미터
  • 테스트 대상 처리 실행
  • 출력 데이터
  • 어설션

  • 전 준비는, setUp() 메소드안이라든가, 테스트 메소드의 선두에서 합니다만, 테스트 케이스에 의해 몇개의 패턴이 있거나 하면 테스트 메소드내에서 조건 분기 하거나 해 전망이 나빠집니다. 또한, 어설션도 마찬가지이며, 테스트 대상의 메소드를 실행한 뒤에, 어긋남과 어서션 메소드가 계속되면 잘 모르는 간지가 되어 버립니다.

    그래서 테스트 메소드가 다음과 같은 간지의 깔끔한 구조가 되도록 하고 싶습니다.
    public function testSomething($preparation, $parameters, $assertion)
    {
        $preparation();
        $testTarget = new TestTarget();
        $actual = $testTarget->something($parameters);
        $assertion($actual);
    }
    

    구현



    데이터 제공자


    public function dataSomething()
    {
        $preparations = $assertions = [];
    
        // これをパターン分用意する、共通部分は変数に切り出す
        // 長くなるようなら別メソッドに切り出す
        $preparations['success'] = function (array $dependencies) {
            $someModel = factory(SomeModel::class)->create();
            $someModel->someAction($dependencies['value']);
            return ['someModel' => $someModel];
        };
    
        // こっちはパターンに依存する値を渡せるようにした
        // これも長くなるようなら別メソッドに切り出す
        $assertions['success'] = function ($value) {
            return function ($actual) use ($value) {
                $this->assertSame($value, $actual);
            };
        };
    
        return [
            'success.pattern-01' => [
                'preparation' => $preparations['success'],
                'parameters'  => [...],
                'assertion'   => $assertions['success']('parameter-01'),
            ],
        ];
    }
    

    위의 예에서 $preparation는 Laravel 모델 팩토리를 사용하여 테스트 실행에 필요한 데이터베이스 상태를 준비하는 클로저입니다. 몇 가지 테스트 케이스로 분류할 수 있다(성공과 실패의 2패턴이라든가)라면 베타 쓰기로 패턴분 준비해도 좋을지도 모릅니다.
    $assertion (은)는, 테스트 케이스 마다 파라미터를 건네줄 수 있도록(듯이), 클로저를 돌려주는 클로저로 한 패턴입니다.

    상황에 따라 구분하면 좋지 않을까 생각합니다.

    테스트 방법


    public function testSomething($preparation, $parameters, $assertion)
    {
        $commonData ['value' => ...];
        $preparedData = $preparation($commonData);
        $testTarget = new TestTarget($preparedData);
        $actual = $testTarget->doSomething($parameters);
        $assertion($actual);
    }
    

    라는 느낌으로 할 수 있었습니다.

    결론



    어땠을까요, 무엇을 테스트하고 있는지를 확실히 보고 알 수 있듯이, 테스트 메소드내의 처리는 가능한 한 간단하게 해 두고 싶었으므로, 위와 같은 방법을 취해 보았습니다. 그 밖에도 이런 궁리를 하고 있어, 같은 것이 있으면 코멘트란에서 가르쳐 주세요.

    좋은 웹페이지 즐겨찾기