PHPUnitの各テスト項目の直前直後だったり、全体の最初と最後に処理させたいってことありますよね。 今回はそれの実現の仕方についてと動きについて紹介したいと思います。
テスト全体の最初と最後
まずは、最初と最後に処理させたいパターンについてです。
PHPUnitの公式サイトにも書いてありますが、PHPUnit の拡張について読むとわかると思います。
TestRunnerの拡張をすることで、実現できるみたいで、いくつかあるフックインターフェイスの中のBeforeFirstTestHook
とAfterLastTestHook
を用いて実装します。
実装方法
では、実装方法です。以下のページのTestRunner エクステンションの組み込みという項目を参考にしながら実装していきます。
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には、各クラスの実行前後だったり、各テストの実行前後に処理を加えることができます。 そちらの確認をしたいなと思います。
公式ドキュメントにはこちらのフィクスチャのページで紹介されていますね。
ざっくりとですが、以下のようなものを紹介したいと思います。
- 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 A
とClass 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)
おお、わかりやすい結果です!(自分にとっては)
これを図で表してみました。
今回の実験で、executeBeforeFirstTest, setUpBeforeClass, setUp, tearDown, tearDownAfterClass, executeAfterLastTestはそれぞれこの順序なのかなと予想されますね。
さいごに
ということで、今回は各テストの前処理・後処理などをしたいときに使用するメソッドがどれが適切かってのを改めて確認できたかなと思います。