PHPUnitのバージョン上げようとして嵌った
環境
- Laravel 5.3.x / Laravel 5.5.x の2つのアプリケーションが存在
- PHP 7.2.x
やりたいこと
どちらも最新バージョンのPHPUnit(8.x)が使いたい
事象と原因
Laravel 5.3.xのアプリケーション
PHP Fatal error: Class 'PHPUnit_Framework_TestCase' not found in application/path/vendor/laravel/framework/src/Illuminate/Foundation/Testing/TestCase.php on line 11
このエラーが発生
Laravel5.4からPHPUnitのクラス名の名前空間化?に対応したらしく、 以下の記述をするLaravel5.3でエラーが発生
use PHPUnit_Framework_TestCase; abstract class TestCase extends PHPUnit_Framework_TestCase
Laravel5.4以降
use PHPUnit\Framework\TestCase as BaseTestCase; abstract class TestCase extends BaseTestCase
対応策
PHPUnitのバージョンを上げない
細かく言うと
- vendor配下のモジュールのためオーバーライドする必要がある(と思う)
- バージョンを上げることはwantであり、mustではない
Laravel 5.5.xのアプリケーション
PHP Fatal error: Declaration of Illuminate\Foundation\Testing\TestCase::setUp() must be compatible with PHPUnit\Framework\TestCase::setUp(): void in application/path/vendor/laravel/framework/src/Illuminate/Foundation/Testing/TestCase.php on line 12
ググってもよく分からなくて、後輩に聞いたら教えてくれた。
Return Type of Template Methods The methods listed below now have a void return type declaration:
PHPUnit\Framework\TestCase::setUpBeforeClass() PHPUnit\Framework\TestCase::setUp() PHPUnit\Framework\TestCase::assertPreConditions() PHPUnit\Framework\TestCase::assertPostConditions() PHPUnit\Framework\TestCase::tearDown() PHPUnit\Framework\TestCase::tearDownAfterClass() PHPUnit\Framework\TestCase::onNotSuccessfulTest() Your implementations of the methods listed above now must be declared void, too, otherwise you will get a compiler error.
この一文にびっくり「otherwise you will get a compiler error.」
ということで、上記に当てはまるメソッドに対して、
: void
を記述したらエラーが解消された。
/** * Setup the test environment. * * @return void */ protected function setUp(): void {
対応策
PHPUnitのバージョンを上げない
細かく言うと
- Laravel5.3のときと同様に、vendor配下のモジュールのためオーバーライドする必要がある(と思う)
- 既存のテストコードに対しても修正が必要で、意外と工数が掛かることが判明
既存のテストコードでのエラー
/** * XXXXXTest constructor. * * @param string|null $name * @param array $data * @param string $dataName */ public function __construct(string $name = null, array $data = [], string $dataName = '') {
__constructをこう実装していたのだが、
PHP Fatal error: Uncaught TypeError: Argument 3 passed to Tests\Feature\XXXXXTest::__construct() must be of the type string, integer given
エラーが発生してしまった。
/** * GetUserTest constructor. * * @param string|null $name * @param array $data * @param $dataName */ public function __construct(string $name = null, array $data = [], $dataName = '') {
こう直したら動いたのだが、Warningが発生しててあまり綺麗とは言えなかった。
PHPUnit 8.0.4 by Sebastian Bergmann and contributors. Warning - The configuration file did not pass validation! The following problems have been detected: Line 26: - Element 'log', attribute 'logIncompleteSkipped': The attribute 'logIncompleteSkipped' is not allowed. Test results may not be as expected. ......... 9 / 9 (100%) Time: 3.07 seconds, Memory: 24.00 MB
補足
戻り値の型問題は、Laravel5.8で修正されているので、
Laravel5.7 以下ではPHPUnit8.xは使わない方がよさそう。という見解を得られた。