type holyshared = Engineer<mixed>

技術的なことなど色々

Expectationを再設計した話。

expectationを開発していて、ちょっと気に入らない箇所がいくつか出てきたので、再設計してみた。

再設計したので、expectationはもうメンテしておらず、 expectに変わったので、注意してください。 また、peridotプラグインも、peridot-expect-pluginに変わり、再設計した方のものに変わっています。

再設計後のマッチャーAPIは互換性担保しているはず。
設計を見直した点は、下記の通り。

  1. アノテーションを使用するメリットがそんなになかった。

    旧ロジックはアノテーションでMatcherのどのメソッドを使用して、評価するかを指定する設計だった。 こんな感じで、アノテーションで指定する。

     ```php
     /**
      * @Lookup(name="toEqual")
      * @Lookup(name="toBe")
      * @param mixed $actual
      */
     public function match($actual)
     {
         $this->setActualValue($actual);
         return $this->getExpectValue() === $this->getActualValue();
     }
    
     /**
      * @Lookup(name="toBeTrue")
      */
     public function matchTrue($actual)
     {
         return $this->setExpectValue(true)->match($actual);
     }
     ```
    

    アノテーションエイリアス割り当てられるくらいのメリットぐらいしかなかったので、使わないようにした。

  2. Matcherのソースコードに対する、対応付けがわかりににくい。

    Matcherをソースコードと1対1になるようにした。

    • 例: toBeTrue -> ToBeTrue.php
    • 例: toBeEqual -> ToBeEqual.php
  3. エラーメッセージがわかりにくい。

    rspec-expectationsgomegaあたりが、どうしているか参考にした。

Peridotのプラグインを使用していた人へ

移行はそんな難しくなくて、peridot.phpを編集して、ExpectationPluginの部分をExpectPluginにします。 基本的にはこれでOKなはず。

use expect\peridot\ExpectPlugin;

return function(EventEmitterInterface $emitter) {
    ExpectPlugin::create()->registerTo($emitter);
};

あとはspec書くだけ。

describe('Example', function() {
    describe('#create', function() {
        it('return new Example instance', function() {
            expect(Example::create())->toBeAnInstanceOf('Example');
        });
    });
});

まとめ