てくてくテック

【Laravel】テストで使用するsetUpメソッドについて

setUpメソッドって?

laravelではsetUpメソッドというものがあり、これはテストを書く際に複数のテストで使用するような値を事前に定義しておきたい場合などに使います。

例えば以下のようなテストがあったとしましょう。

namespace Tests\Unit;

use PHPUnit\Framework\TestCase;

class ExampleTest extends TestCase
{
    /**
     * AテストとBテスト
     */
    public function ATest()
    {
        ...
    }
    public function BTest()
    {
        ...
    }
}

ここで、ファイルをおけるストレージだったり、別のクラスのインスタンスをAでもBでも使いたい場合があったとします。

すると...


class ExampleTest extends TestCase
{
    /**
     * AテストとBテスト
     */
    public function ATest()
    {
        $this->fakeStorage('hoge');
        $this->hoge = new Hoge();
    }
    public function BTest()
    {
        $this->fakeStorage('hoge');
        $this->hoge = new Hoge();
        ...
    }
}

このように同じ処理が複数箇所に出てきてしまい、DRY(dont repeat yourself)ではない設計になってしまいます。

こういった共通のインスタンスやストレージ定義などをまとめて置けるのがsetUpメソッドなのです!

ちなみに、こういったテストの事前処理は"フィクスチャ"と呼ばれるようです。(テスト後の処理も含めてそう呼ぶらしい)

ニュアンスとしてはおそらく、テストの環境をしっかり整えるといった具合かなと。

簡単に書くと以下のような感じです。(...は後続処理)

  public function setUp() :void
  {
      parent::setUp();
      ...
  }

このsetUpメソッドにはparent::setUp()が必要です。

公式曰く、"確実に呼び出してください"とのことです...

気になる方は以下のボタンから参照してみてください。

簡単にお伝えしておくと、独自に各テストクラスに対して自分たち用にカスタマイズしたsetUpを定義するわけですが、すでにデフォルトでテストの前に行わなければいけない処理がそのextends元のsetUpメソッドに書いてあるわけです。

独自にメソッドを定義した場合、当然、そのsetUpメソッドは呼ばれなくなります。(処理を上書きするので...詳しくは"PHP オーバーライド"で検索検索ぅ!)

すると、テストする前にやって欲しい事前処理を上書きして自前の事前処理をすることになるわけです。

なので、parentを使って、あなたの好きなセットアップを定義してもいいんだけど、僕らがして欲しい処理もちゃんと呼び出すようにね!ってわけです。たぶん。

ちなみに、いままでさもlaravelのお話をしているように話してきましたが、実はこのテストで使っているSetUpメソッドはPHPUnitというものだったりします。

詳しくは以下辺りに凝縮されているので、是非一読してみてください。

使おうとした

さて、それではそのsetUpメソッドを使ってみましょう!

普通のメソッドと同じように定義してあげれば使うことができます!

namespace Tests\Unit;

use PHPUnit\Framework\TestCase;

class ExampleTest extends TestCase
{

    private hoge;

    // この中で設定した値は全てのテストから使うことができる!
    public function setUp()
    {
        parent::setUp();
        $this->fakeStorage('hoge');
        $this->ihoge = new Hoge();
    }

    /**
     * AテストとBテスト
     */
    public function ATest()
    {
        ...
    }
    public function BTest()
    {
        ...
    }
}

これできっとうまくいくはずだっ!

っと思ったんですが...

ここでエラーが発生してしまったんですよね...

PHP Fatal error:  Declaration of Tests\Unit\ExampleTest::setUp() must be compatible with Illuminate\Foundation\Testing\TestCase::setUp(): void in /var/www/tests/Unit/ExampleTest.php on line 14

PHP Fatal error: Declaration of setUp must be compatible with...といったエラーが出てきました。

これは、extends元(今回はTestCase)にて定義されているsetUp()メソッドと返り値が違いますよ〜って怒られています。

ではではと、TestCaseをみてみると、以下のように返り値はvoidだよ〜!ってタイプヒンティングされていました。

function setUp() :void
{
   ...
}

それに対して、僕が書いたsetupにも同じくタイプヒンティングをすることで無事動きました!

public function setUp() :void
{
    parent::setUp();
    $this->fakeStorage('hoge');
    $this->ihoge = new Hoge();
}

ちなみに...

さて、今回継承(extends)をしており、その際にタイプヒンティングを合わせないと"compatibleうんたら〜"っていうエラーがでました。

これ、テストのsetUpメソッドでなくても出てくるので、気をつけなきゃですね...!

なんらかのメソッド定義をした時にcompatibleうんたらのエラーが出てきたらextendsを怪しめ!って学びました。

returnしないからといってサボタージュはできないですね...w

まとめ

今回はsetUpメソッドについて調べてみました!

テストを書くときに同じ共通の定数や変数等を使用する場合は特にsetUpに詰め込んでおけば事前処理なんだな〜ってわかりやすいのでいいですよね!

テストも読みやすく設計していきましょう!

モバイルバージョンを終了