【Laravel】テスト時のmarkTestIncompleteについて

どーも!

たかぽんです!

今回はテストまわりを眺めていてふと見つけた知らない内容について書いていきます!

markTestIncomplete

さて、それでは今回筆者が見つけたのはmarkTestIncompleteというメソッドでした。

laravelのテストファイルをみていたのですが、上記のメソッドを見つけ...

これはなんだ・・・?と。

調べてみた感じだと、テストの実装が必要(あった方が良い)なんだけど、訳あってまだ実装していないよ!

ってことを示したいケースなどに使われるみたいです。

厳密にはLaravelというよりPHPunitなんですが...

公式資料は以下をご参考ください。

では実際にテストを回した場合の挙動はどうなるのか?

気になりますよね!

ためしてみました!

まずは特に何も設定していない、デフォルトのテストを回した場合です。

(base) taka@Taka laravelPractice % php artisan test

   PASS  Tests\Unit\ExampleTest
  ✓ that true is true

   PASS  Tests\Feature\ExampleTest
  ✓ the application returns a successful response

  Tests:  2 passed
  Time:   0.09s

laravelをインストールした際のExampleテストが回っていることがわかります。

今回はUNITテストの方を修正して、上記のmarkTestIncompleteとして扱っていこうと思います。

初期のUnitにあるExampleTestの中身は以下です。

<?php

namespace Tests\Unit;

use PHPUnit\Framework\TestCase;

class ExampleTest extends TestCase
{
    /**
     * A basic test example.
     *
     * @return void
     */
    public function test_that_true_is_true()
    {
        $this->assertTrue(true);
    }
}

assertTrueに常にtrueを渡しているので、絶対に成功するテストになっています。

では、これを前述した公式の例をもとに、以下のように書き換えます。

<?php

namespace Tests\Unit;

use PHPUnit\Framework\TestCase;

class ExampleTest extends TestCase
{
    /**
     * A basic test example.
     *
     * @return void
     */
    public function test_that_true_is_true()
    {
        $this->assertTrue(true);
        // Stop here and mark this test as incomplete.
        $this->markTestIncomplete(
            'This test has not been implemented yet.'
        );
    }
}

assertの後にmarkTestIncompleteを入れています。

上記の形でテストを実行してみると...?

(base) taka@Taka laravelPractice % php artisan test

   WARN  Tests\Unit\ExampleTest
  … that true is true → This test has not been implemented yet.

   PASS  Tests\Feature\ExampleTest
  ✓ the application returns a successful response

  Tests:  1 incompleted, 1 passed
  Time:   0.09s

こうなりました。

先程はsuccessとなっていましたが...incompletedとなっていますね。

このincompletedがあることにより、あ、まだ未実装のテストがどっかにあるんだな?っていうことがわかる訳です!

また、今回assertTrueを残していました。

これは、途中までテストを実装して、途中まで正しく動く形にして、残りの部分はincompleteにしておく...といった場合に使えるようです。

メソッド丸々incompleteももちろん可能ですが、場合によって使い分けると良さそうですね!

もしincompleteの実装内容でfalseになるとどうなる?

incompleteの実装をした場合、途中まで実装はしてしまえることがわかりました。

先程はassertTrueに対して常にtrueを渡していたので、失敗しない前提のテストでした。

しかし、これが失敗した場合はどうでしょうか...?

    public function test_that_true_is_true()
    {
        $this->assertTrue(false);
        // Stop here and mark this test as incomplete.
        $this->markTestIncomplete(
            'This test has not been implemented yet.'
        );
    }

こんな感じで、常にfalseを返して試してみます。

すると...?

(base) taka@Taka laravelPractice % php artisan test

   FAIL  Tests\Unit\ExampleTest
  ⨯ that true is true

   PASS  Tests\Feature\ExampleTest
  ✓ the application returns a successful response

  ---

  • Tests\Unit\ExampleTest > that true is true
  Failed asserting that false is true.

  at tests/Unit/ExampleTest.php:16
     12▕      * @return void
     13▕      */
     14▕     public function test_that_true_is_true()
     15▕     {
  ➜  16▕         $this->assertTrue(false);
     17▕         // Stop here and mark this test as incomplete.
     18▕         $this->markTestIncomplete(
     19▕             'This test has not been implemented yet.'
     20▕         );


  Tests:  1 failed, 1 passed
  Time:   0.09s

該当のテストがfailedとなりました...!

例えばですが...もしまだ未実装の機能だったり、今後変更予定の機能に対するテストを実装する際、まだ正しく動かないけど、markTestIncompleteにしたい場合...などは気をつけなければ行けなさそうです...

確かにmarkTestIncompleteだけど、途中まで実装しているテストがこけてしまうので、テスト実行時にfailedになってしまいます。

例えば、実装は機能ができたから行う、assertの部分は一旦trueになる仮値を入れておく...といった対処をしなければ逆に混乱を招きそうですね...

その点は注意して使う必要がありそうです。

まとめ

さて、今回はlaravelでテストに使えるmarkTestIncompleteについて調べてみました!

知らなかったので、最初見た時はなんだこれ?ってなりましたが、今後機会があれば使ってみようと思います...!

本当は後回しにせずに可能な限り実装すべきな気もしますが...

それでわ!

おすすめの記事