ポンコツエンジニアのごじゃっぺ開発日記。

いろいろポンコツだけど、気にするな。エンジニアの日々の開発などの記録を残していきます。 自動で収入を得られるサービスやシステムを作ることが目標!!

【PHP】PHPUnitの一番最初と一番最後に処理させる方法と実行前後のタイミングについて

PHPUnitの各テスト項目の直前直後だったり、全体の最初と最後に処理させたいってことありますよね。 今回はそれの実現の仕方についてと動きについて紹介したいと思います。

テスト全体の最初と最後

まずは、最初と最後に処理させたいパターンについてです。

PHPUnitの公式サイトにも書いてありますが、PHPUnit の拡張について読むとわかると思います。

phpunit.readthedocs.io

TestRunnerの拡張をすることで、実現できるみたいで、いくつかあるフックインターフェイスの中のBeforeFirstTestHookAfterLastTestHookを用いて実装します。

実装方法

では、実装方法です。以下のページのTestRunner エクステンションの組み込みという項目を参考にしながら実装していきます。

phpunit.readthedocs.io

MyExtensionクラスを作成していきます。

MyExtension.php

<?php

namespace App;

use PHPUnit\Runner\AfterLastTestHook;
use PHPUnit\Runner\BeforeFirstTestHook;

final class MyExtension implements BeforeFirstTestHook, AfterLastTestHook
{
    public function executeAfterLastTest(): void
    {
        // 最後のテストの実行後にコールされます
        echo "\n\n== executeAfterLastTest\n\n";
    }

    public function executeBeforeFirstTest(): void
    {
        // 最初のテストの実行前にコールされます
        echo "\n\n== executeBeforeFirstTest\n\n";
    }
}

クラスを作成した後に、例えば以下のようなphpunit.xmlがあったとします。

<phpunit bootstrap="vendor/autoload.php">
    <testsuites>
        <testsuite name="App test">
            <directory>tests</directory>
        </testsuite>
    </testsuites>
</phpunit>

これに対して、extensionを追加します。

<phpunit bootstrap="vendor/autoload.php">
    <testsuites>
        <testsuite name="App test">
            <directory>tests</directory>
        </testsuite>
    </testsuites>
    <extensions>
        <extension class="App\MyExtension"/>
    </extensions>
</phpunit>

これだけで完了です。

では、実行してみましょう。

$ phpunit
PHPUnit 8.5.2 by Sebastian Bergmann and contributors.



== executeBeforeFirstTest

....                                                                4 / 4 (100%)

== executeAfterLastTest



Time: 1.33 seconds, Memory: 6.00 MB

OK (4 tests, 20 assertions)

このように、テスト開始時と終了時にechoで文字が出力できましたね。

実行前後のタイミング確認

さて、phpunitには、各クラスの実行前後だったり、各テストの実行前後に処理を加えることができます。 そちらの確認をしたいなと思います。

公式ドキュメントにはこちらのフィクスチャのページで紹介されていますね。

phpunit.readthedocs.io

ざっくりとですが、以下のようなものを紹介したいと思います。

  • setUpBeforeClass
    • テストケースクラスの最初に実行される
  • tearDownAfterClass
    • テストケースクラスの最後に実行される
  • setUp
    • 各テストメソッドが実行される前に実行される
  • tearDown
    • 各テストメソッドが実行された後に実行される

これらをそれぞれのテストケースクラスに挿入していきたいと思います。

<?php

namespace App;

class HogeTest extends \PHPUnit\Framework\TestCase
{
    public static function setUpBeforeClass(): void
    {
        echo "\n== Class A: setUpBeforeClass\n";
    }

    public static function tearDownAfterClass(): void
    {
        echo "\n== Class A: tearDownAfterClass\n";
    }

    protected function setUp(): void
    {
        echo "\n== Class A: setUp\n";
    }
    protected function tearDown(): void
    {
        echo "\n== Class A: tearDown\n";
    }

    // この下にテストを書く

このような標準出力をすることで、動作の順序の確認をしたいと思います。

今回用意したのは、以下です。2つずつ用意すればわかるっしょってことで。

  • テストケースクラス:2つ
  • テストメソッド:4つ(1クラスに2つ)

想像がつくかもしれないですが、出力はClass AClass Bで見分けられるようにしています。

このログを埋め込んで、実行してみましょう。

phpunit
PHPUnit 8.5.2 by Sebastian Bergmann and contributors.



== executeBeforeFirstTest


== Class A: setUpBeforeClass
.
== Class A: setUp

== Class A: tearDown
.
== Class A: setUp

== Class A: tearDown

== Class A: tearDownAfterClass

== Class B: setUpBeforeClass
.
== Class B: setUp

== Class B: tearDown
.                                                                4 / 4 (100%)
== Class B: setUp

== Class B: tearDown

== Class B: tearDownAfterClass


== executeAfterLastTest



Time: 755 ms, Memory: 6.00 MB

OK (4 tests, 20 assertions)

おお、わかりやすい結果です!(自分にとっては)

これを図で表してみました。

f:id:ponkotsu0605:20200925224316j:plain
phpunitのフィクスチャの実行順序

今回の実験で、executeBeforeFirstTest, setUpBeforeClass, setUp, tearDown, tearDownAfterClass, executeAfterLastTestはそれぞれこの順序なのかなと予想されますね。

さいごに

ということで、今回は各テストの前処理・後処理などをしたいときに使用するメソッドがどれが適切かってのを改めて確認できたかなと思います。

お問い合わせプライバシーポリシー制作物