PHPUnitでテストケース個別の事前/事後処理をしたいんだけどなぁ

setUp/tearDownってクラス単位で生やしてテストケース実行時に処理が走りますけど、アレをテストケース(メソッド)単位で指定できたら良いのになぁ・・・って気持ちがあるんですね。何か設計が間違っているのかもだけど。
例えば「DBをいじくり回すケースの前に中身をキレイにしておきたいな」とか。同じクラスであっても、全部のケースの前で実行されると処理が無駄になりそうだなぁ的な

こういう感じのことですね。
デコレータでは無いが

<?php
    #[CaseDecorate(before: 'beforeNanika')]
    public function testFix()
    {
        $data = ['a', 'b', 'c'];

        $actual = ArrayUtil::fix($data);
        $this->assertSame($data, $actual->toArray());
    }

    #[CaseDecorate(after: 'afterNanika')]
    public function testFix2()
    {
        $data = ['a', 'b', 'c'];

        $actual = ArrayUtil::fix($data);
        $this->assertSame($data, $actual->toArray());
    }

    public static function beforeNanika()
    {
        var_dump(__METHOD__);
    }

    public static function afterNanika()
    {
        var_dump(__METHOD__);
    }

何か簡単な方法を用意できないものか??って願望があるのですが、本体や誰かのプラグインで用意されてても良さそうだよなーって思いつつあんまりちゃんと調べてないです。

Extension書いたら出来るんかな?
・・そう、私はPHPUnitのExtensionを作ることができるので!*1

fortee.jp

で、実際に動きはするやつを落書きしてみたのがコチラ (run in separationとかdata provider周りの、 TestSuite の挙動が変わる奴については動作確認取ってないです)

github.com

どう思います?

作ってみて感じたのは、

  • Emitter経由でEventを受け取る仕組みだと、TestCaseオブジェクトそのものを受け取るわけではないので、インスタンスメソッドを使えない
    • コレが使い勝手を悪くするなぁ。DB接続とか、インスタンス欲しいね
    • setUp()とかBefore attributesを使った標準の仕組みだと、TestRunnerが直に呼び出してくれるので使えるのだけども
    • 某FWのObjectPool+Facadeっぽいやつとは相性良さそう
  • 名前、「デコレータ」にしてるけど実現が難しそう
    • 実行前・後でラップしたり、実行結果自体を自分で直接観測できたら出来ることが増えそうなんだけどなぁ
      • とはいえテストケース(メソッド)は戻り値を持つわけではないから、あんまり要らないけど
      • テストの実行結果とかはEventの種類で分かるし、assertの実行結果とかも購読できる訳で
    • TestRunner自体を自分で書けば出来るんだけども、モチロンやりたくない

みたいな所ですかね〜

*1:このプロポーザルに対応する資料がアレばよかったのに、作ってないから思い出すのに少し時間がかかった