web-dev-qa-db-ja.com

ユニットテストオブジェクト用のファクトリを作成するための最善の方法は何ですか?

私はTDDを習得しようとしていて、カスタムオブジェクトのためのファクトリの作成に苦労しています。たとえば、カスタムユーザータイプがあり、そのタイプのすべてのユーザーが特定の機能を持っている必要がある場合は、WP_UnitTestファクトリを使用してユーザーを作成し、オブジェクトを使用する前に各テストにその機能を手動で追加します。さまざまなテストファイルでこれらのオブジェクトを使用する必要があるため、各テストファイル/クラスにファクトリ関数を含めるのは冗長であり、ファクトリメソッドの4つのバリエーション(create、create_and_get、create_many)をすべて手動で実装するのは面倒です。 、およびcreate_and_get_many)。

このようなユニットテストオブジェクト用のファクトリを作成するための最善の方法は何ですか?

1
philosophyguy

私が正しく引き受けたなら、あなたが探しているものはstubsmocksを作成するための良いライブラリです。

あなたがPHPUnitを使用する場合、それはそのための機能を持っています。 https://phpunit.de/manual/current/en/test-doubles.html#test-doubles を参照してください。

たとえば、次のようなクラスがあるとしましょう。

namespace MyApp;

class MyCustomUser {

   public function __construct(\WP_User $user) {
     $this->user = $user;
   }

   public function hasCapability($capability) {
      return $this->user->can($capability);
   }
}

ユーザファクトリを保持するトレイトを作成し、PHPUnitのモック機能を利用することができます。

namespace MyApp\Tests;

trait CreateUserTrait {

   protected function createUser(array $capabilitites) {

      $stub = $this->createMock(MyCustomUser::class);

      $has_capability = function($capability) use ($capabilitites) {
         return in_array($capability, $capabilitites, true);
      };

      $stub->method('hasCapability')->will($this->returnCallback($has_capability));
   }
}

テストクラスのこの時点で、あなたはその特性を使用してファクトリを利用することができます。

namespace MyApp\Tests;

use PHPUnit\Framework\TestCase;

class UserMockTest extends TestCase
{
    use CreateUserTrait;

    public function testUserFactoryWorks()
    {
        $userMock = $this->createUser(['create_post']);

        $this->assertTrue($userMock->hasCapability('create_post'));
    }
}

もちろん、モックとスタブは、モックオブジェクトを利用する other オブジェクトをテストする必要がある場合に便利です。あなたはSUTをあざけらないでしょう。

モックを使用することによる良い副作用は、テストで any WordPress関数またはクラスを使用しなかったことです(たとえ元のユーザーオブジェクトがWordPress WP_Userオブジェクトを使用している場合でも)。 WordPress、 real 単体テストにする:WordPressをロードすると、単体テストではなく、 統合テスト になります。

多くの人がPHPの曖昧な構文を少し 要約するのは難しい と感じます。もしあなたがそのうちの一人なら、 Mockery を見たほうがいいかもしれません。

あなたのニーズによっては、 Faker も助けになるかもしれません。


注:上記のコードではPHP 5.5が必要で、想定されるPHPUnitのバージョンはバージョン5です*。これにはPHP 5.6以降が必要です。

1
gmazzap

私はあなた自身のPHPUnitファクトリを作成するための チュートリアルを書きました 。ただしこの場合は、既存のユーザーファクトリWP_UnitTest_Factory_For_Userを拡張するだけでよいのです。 そのクラスのソース を見ると、たくさんの異なるメソッドを実装する必要はないことがわかります。1つだけです:create_object()。それはあなたが言及した他の方法でも使われるでしょう。

ユーザーファクトリのメソッドは次のようになります。

function create_object( $args ) {
    return wp_insert_user( $args );
}

とても簡単ですね。

だからあなたがする必要があるのはそれをするためにそれを修正することだけですそのファクトリの子クラスを作成すること、これのようなもの:

class WP_UnitTest_Factory_For_User_With_Cap extends WP_UnitTest_Factory_For_User {

    function create_object( $args ) {
        $user_id = parent::create_object( $args );

        if ( $user_id ) {
            $user = new WP_User( $user_id );
            $user->add_cap( 'my_custom_cap' );
        }

        return $user_id;
    }
}

それであなたはあなたのsetUp()メソッドでこのようなことをすることができます:

$this->factory->user_with_cap = new WP_UnitTest_Factory_For_User_With_Cap( $this->factory );

これであなたのテストでは、あなたが作成されるためにそのキャップを持ったユーザーを必要とするそれぞれの場所で$this->factory->user$this->factory->user_with_capに置き換えることができます。


別の方法としては、WP_UnitTestCaseの子である独自のカスタム抽象テストケースクラスを作成し、そこからすべてのテストケースを拡張することです。その後、そのクラスにファクトリメソッドを作成できます。ただし、これはすべてのテストケースを単一の親から拡張できる場合にのみ機能します。たとえば、Ajaxテストがある場合はそうではないかもしれません。

1
J.D.