Slide 1

Slide 1 text

PHPカンファレンス福岡 2024 2024/06/22 @02 PHPUnit 11 概論

Slide 2

Slide 2 text

© 2012-2024 BASE, Inc. #phpconfuk BASE, Inc. BASE BANK 振込申請チーム Engineering Program Manager / フルサイクルエンジニア PHPカンファレンス2024 実行委員長 02 大津 和槻(おおつ かずき) :@cocoeyes02 自己紹介

Slide 3

Slide 3 text

© 2012-2024 BASE, Inc. #phpconfuk PHPUnit 11のアップデートについて 時間が許す限り解説します 15分しか無いので早速本題

Slide 4

Slide 4 text

© 2012-2024 BASE, Inc. #phpconfuk 今回話す内容 4 ● PHP 8.2以上が必須に ● テストスタブでexpectsが非推奨に ● TestCase / MockBuilderクラスのメソッドがいくつか非推奨に ● コメント(アノテーション)を使用したメタデータが非推奨に ● dataprovider周りの仕様変更 ● 新しく追加されたアサーション、オプション

Slide 5

Slide 5 text

PHP 8.2以上が必須に

Slide 6

Slide 6 text

© 2012-2024 BASE, Inc. #phpconfuk PHP 8.2以上が必須に 6 https://phpunit.de/supported-versions.html

Slide 7

Slide 7 text

© 2012-2024 BASE, Inc. #phpconfuk PHP 8.2以上が必須に 7 https://www.php.net/supported-versions.php

Slide 8

Slide 8 text

テストスタブで expectsが非推奨に

Slide 9

Slide 9 text

© 2012-2024 BASE, Inc. #phpconfuk テストスタブでexpectsが非推奨に 9 おさらい:PHPUnitのテストダブルは2種類存在します。 (詳細はドキュメントへ) ● テストスタブ ○ あらかじめ決められた戻り値や例外などを返すオブジェクト ○ 代表的なメソッド:willreturn、willThrowException ● モックオブジェクト ○ メソッドの呼び出し回数や引数など呼び出され方を検証するオブ ジェクト ○ テストスタブのメソッドも使える ○ 代表的なメソッド:expects、with

Slide 10

Slide 10 text

© 2012-2024 BASE, Inc. #phpconfuk テストスタブでexpectsが非推奨に 10 おさらい:PHPUnitのテストダブルは2種類存在します。 (詳細はドキュメントへ) ● テストスタブ ○ あらかじめ決められた戻り値や例外などを返すオブジェクト ○ 代表的なメソッド:willreturn、willThrowException ● モックオブジェクト ○ メソッドの呼び出し回数や引数など呼び出され方を検証するオブ ジェクト ○ テストスタブのメソッドも使える ○ 代表的なメソッド:expects、with

Slide 11

Slide 11 text

© 2012-2024 BASE, Inc. #phpconfuk テストスタブでexpectsが非推奨に 11 createMock(Observer::class); $mock->expects($this->once()) ->method('update') ->with($this->identicalTo('something')); createStub(Observer::class); $stub->expects($this->once()) ->method('doSomething') ->willReturn('foo'); テストスタブで、expectsメソッドが非推奨になりました。 →メソッドの呼び出し回数を検証するのは、モックオブジェクトの役割のため PHPUnit11で非推奨、PHPUnit12で削除になるようです。

Slide 12

Slide 12 text

TestCase / MockBuilder クラスのメソッドが いくつか非推奨に

Slide 13

Slide 13 text

© 2012-2024 BASE, Inc. #phpconfuk TestCase / MockBuilderクラスの メソッドがいくつか非推奨に 13 TestCase ● iniSet() ● setLocale() ● createTestProxy() ● getMockForTrait() ● getObjectForTrait() ● getMockForAbstractClass() ● returnValue() ● onConsecutiveCalls() ● returnValueMap() ● returnArgument() ● returnSelf() ● returnCallback()

Slide 14

Slide 14 text

© 2012-2024 BASE, Inc. #phpconfuk TestCase / MockBuilderクラスの メソッドがいくつか非推奨に 14 TestCase ● iniSet() ● setLocale() ● createTestProxy() ● getMockForTrait() ● getObjectForTrait() ● getMockForAbstractClass() ● returnValue() ● onConsecutiveCalls() ● returnValueMap() ● returnArgument() ● returnSelf() ● returnCallback()

Slide 15

Slide 15 text

© 2012-2024 BASE, Inc. #phpconfuk TestCase / MockBuilderクラスの メソッドがいくつか非推奨に 15 https://github.com/sebastianbergmann/phpunit/issues/5243

Slide 16

Slide 16 text

© 2012-2024 BASE, Inc. #phpconfuk TestCase / MockBuilderクラスの メソッドがいくつか非推奨に 16 https://github.com/sebastianbergmann/phpunit/issues/5243

Slide 17

Slide 17 text

© 2012-2024 BASE, Inc. #phpconfuk TestCase / MockBuilderクラスの メソッドがいくつか非推奨に 17 (前略) このgetMockForTrait()メソッドは、指定された特性を使用する空のクラ スのモック オブジェクトを返します。 指定された特性のすべての抽象メソッドがモック化されます。これによ り、特性の具体的なメソッドをテストできます。 何かをテストするためにgetMockForTrait()を使用する必要があるのは、 ほとんどの場合、コードの臭いが発生します。つまり、テスト対象システ ムのソフトウェア設計に何か問題があるということです。 (後略) https://github.com/sebastianbergmann/phpunit/issues/5243

Slide 18

Slide 18 text

© 2012-2024 BASE, Inc. #phpconfuk TestCase / MockBuilderクラスの メソッドがいくつか非推奨に 18 何かをテストするためにgetMockForTrait()を使用する必要があるのは、 ほとんどの場合、コードの臭いが発生します。 つまり、テスト対象システムのソフトウェア設計に何か問題があるという ことです。 https://github.com/sebastianbergmann/phpunit/issues/5243

Slide 19

Slide 19 text

© 2012-2024 BASE, Inc. #phpconfuk TestCase / MockBuilderクラスの メソッドがいくつか非推奨に 19 何かをテストするためにgetMockForTrait() / getObjectForTrait()を使 用する必要があるのは、ほとんどの場合、コードの臭いが発生します。 つまり、テスト対象システムのソフトウェア設計に何か問題があるという ことです。 https://github.com/sebastianbergmann/phpunit/issues/5244 https://github.com/sebastianbergmann/phpunit/issues/5243

Slide 20

Slide 20 text

© 2012-2024 BASE, Inc. #phpconfuk TestCase / MockBuilderクラスの メソッドがいくつか非推奨に 20 何かをテストするためにgetMockForTrait() / getObjectForTrait() / getMockForAbstractClass()を使用する必要があるのは、ほとんどの場 合、コードの臭いが発生します。 つまり、テスト対象システムのソフトウェア設計に何か問題があるという ことです。 https://github.com/sebastianbergmann/phpunit/issues/5245 https://github.com/sebastianbergmann/phpunit/issues/5244 https://github.com/sebastianbergmann/phpunit/issues/5243

Slide 21

Slide 21 text

© 2012-2024 BASE, Inc. #phpconfuk TestCase / MockBuilderクラスの メソッドがいくつか非推奨に 21 何かをテストするためにgetMockForTrait() / getObjectForTrait() / getMockForAbstractClass()を使用する必要があるのは、ほとんどの場 合、コードの臭いが発生します。 つまり、テスト対象システムのソフトウェア設計に何か問題があるという ことです。 https://github.com/sebastianbergmann/phpunit/issues/5245 https://github.com/sebastianbergmann/phpunit/issues/5244 https://github.com/sebastianbergmann/phpunit/issues/5243 😭

Slide 22

Slide 22 text

© 2012-2024 BASE, Inc. #phpconfuk TestCase / MockBuilderクラスの メソッドがいくつか非推奨に 22 TestCase ● iniSet() ● setLocale() ● createTestProxy() ● getMockForTrait() ● getObjectForTrait() ● getMockForAbstractClass() ● returnValue() ● onConsecutiveCalls() ● returnValueMap() ● returnArgument() ● returnSelf() ● returnCallback()

Slide 23

Slide 23 text

© 2012-2024 BASE, Inc. #phpconfuk TestCase / MockBuilderクラスの メソッドがいくつか非推奨に 23 https://github.com/sebastianbergmann/phpunit/issues/5423

Slide 24

Slide 24 text

© 2012-2024 BASE, Inc. #phpconfuk 24 https://github.com/sebastianbergmann/phpunit/issues/5423 TestCase / MockBuilderクラスの メソッドがいくつか非推奨に

Slide 25

Slide 25 text

© 2012-2024 BASE, Inc. #phpconfuk TestCase / MockBuilderクラスの メソッドがいくつか非推奨に 25 MockBuilder ● enableAutoload() ● disableAutoload() ● enableArgumentCloning() ● disableArgumentCloning() ● allowMockingUnknownTypes() ● disallowMockingUnknownTypes() ● enableProxyingToOriginalMethods() ● disableProxyingToOriginalMethods() ● getMockForAbstractClass() ● getMockForTrait() ● setProxyTarget() ● addMethods()

Slide 26

Slide 26 text

© 2012-2024 BASE, Inc. #phpconfuk TestCase / MockBuilderクラスの メソッドがいくつか非推奨に 26 MockBuilder ● enableAutoload() ● disableAutoload() ● enableArgumentCloning() ● disableArgumentCloning() ● allowMockingUnknownTypes() ● disallowMockingUnknownTypes() ● enableProxyingToOriginalMethods() ● disableProxyingToOriginalMethods() ● getMockForAbstractClass() ● getMockForTrait() ● setProxyTarget() ● addMethods()

Slide 27

Slide 27 text

コメント(アノテーション) を使用したメタデータが 非推奨に

Slide 28

Slide 28 text

© 2012-2024 BASE, Inc. #phpconfuk コメント(アノテーション)を使用した メタデータが非推奨に 28 実はPHPUnit 10のときに、予告されていた変更です。 予告通り、PHPUnit11で非推奨になりました。 https://speakerdeck.com/cocoeyes02/introduction-of-phpunit-10?slide=38

Slide 29

Slide 29 text

© 2012-2024 BASE, Inc. #phpconfuk コメント(アノテーション)を使用した メタデータが非推奨に 29

Slide 30

Slide 30 text

© 2012-2024 BASE, Inc. #phpconfuk コメント(アノテーション)を使用した メタデータが非推奨に 30

Slide 31

Slide 31 text

dataprovider周りの 仕様変更

Slide 32

Slide 32 text

© 2012-2024 BASE, Inc. #phpconfuk dataprovider周りの仕様変更 32 以下の条件に当てはまるDataProviderが、エラーになるようになりました。 ● staticではない ● publicではない ● 引数を必要とする 逆にいえば、下記のような形式のDataProviderでないとダメということですね。 public static XXX() {} ちなみにPHPUnit10の時点では、まだ非推奨になっているだけでした。

Slide 33

Slide 33 text

© 2012-2024 BASE, Inc. #phpconfuk dataprovider周りの仕様変更 33 名前付き引数周りでも、下記の仕様が追加されました。 ● どの順番で名前付き引数を設定してもOK ● メソッド引数と一致しない名前付き引数はエラーになる

Slide 34

Slide 34 text

© 2012-2024 BASE, Inc. #phpconfuk dataprovider周りの仕様変更 34 PHPUnit 10では、dataproviderとテストメソッドの引数順を揃える必要があります。 (’c’と書かれていても配列の1番目あるから、1番目の引数である $a に代入される) 1, 'b' => 2, 'c' => 3], // OK ['c' => 3, 'a' => 2, 'b' => 1], // NG ['c' => 1, 'hoge' => 2, 'b' => 3], // OK ]; } #[DataProvider('providerMethod')] public function testAdd($a, $b, $c): void { $this->assertEquals($c, $a + $b); }

Slide 35

Slide 35 text

© 2012-2024 BASE, Inc. #phpconfuk dataprovider周りの仕様変更 35 PHPUnit 10では、dataproviderとテストメソッドの引数順を揃える必要があります。 (’c’と書かれていても配列の1番目あるから、1番目の引数である $a に代入される) 1, 'b' => 2, 'c' => 3], // OK ['c' => 3, 'a' => 2, 'b' => 1], // NG ['c' => 1, 'hoge' => 2, 'b' => 3], // OK ]; } #[DataProvider('providerMethod')] public function testAdd($a, $b, $c): void { $this->assertEquals($c, $a + $b); }

Slide 36

Slide 36 text

© 2012-2024 BASE, Inc. #phpconfuk dataprovider周りの仕様変更 36 PHPUnit 11では、引数順を気にする必要がなくなりました。 ただし、テストメソッドに存在しない引数を指定した場合はエラーになります。 1, 'b' => 2, 'c' => 3], // OK ['c' => 3, 'a' => 2, 'b' => 1], // OK ['c' => 1, 'hoge' => 2, 'b' => 3], // NG ]; } #[DataProvider('providerMethod')] public function testAdd($a, $b, $c): void { $this->assertEquals($c, $a + $b); }

Slide 37

Slide 37 text

© 2012-2024 BASE, Inc. #phpconfuk dataprovider周りの仕様変更 37 PHPUnit 11では、引数順を気にする必要がなくなりました。 ただし、テストメソッドに存在しない引数を指定した場合はエラーになります。 1, 'b' => 2, 'c' => 3], // OK ['c' => 3, 'a' => 2, 'b' => 1], // OK ['c' => 1, 'hoge' => 2, 'b' => 3], // NG ]; } #[DataProvider('providerMethod')] public function testAdd($a, $b, $c): void { $this->assertEquals($c, $a + $b); }

Slide 38

Slide 38 text

© 2012-2024 BASE, Inc. #phpconfuk dataprovider周りの仕様変更 38 PHPUnit 11では、引数順を気にする必要がなくなりました。 ただし、テストメソッドに存在しない引数を指定した場合はエラーになります。 1, 'b' => 2, 'c' => 3], // OK ['c' => 3, 'a' => 2, 'b' => 1], // OK ['c' => 1, 'hoge' => 2, 'b' => 3], // NG ]; } #[DataProvider('providerMethod')] public function testAdd($a, $b, $c): void { $this->assertEquals($c, $a + $b); } ❌

Slide 39

Slide 39 text

新しく追加された アサーション、オプション

Slide 40

Slide 40 text

© 2012-2024 BASE, Inc. #phpconfuk 新しく追加された アサーション、オプション 40 ● assertArrayIsEqualToArrayIgnoringListOfKeys ● assertArrayIsIdenticalToArrayIgnoringListOfKeys ○ 配列のうち指定したキー名以外の値を、緩やかな比較(==)| 厳密比較 (===)する $this->assertArrayIsEqualToArrayIgnoringListOfKeys( [ 'hoge' => '123', 'foo' => 'bar', ], [ 'hoge' => '456', 'foo' => 'baz', ], [ 'hoge',] ); // Failuresになるのは'foo'だけ

Slide 41

Slide 41 text

© 2012-2024 BASE, Inc. #phpconfuk 新しく追加された アサーション、オプション 41 ● assertArrayIsEqualToArrayOnlyConsideringListOfKeys ● assertArrayIsIdenticalToArrayOnlyConsideringListOfKeys ○ 配列のうち指定したキー名のみの値を、緩やかな比較(==)| 厳密比較 (===)する $this->assertArrayIsEqualToArrayOnlyConsideringListOfKeys( [ 'hoge' => '123', 'foo' => 'bar', ], [ 'hoge' => '456', 'foo' => 'baz', ], [ 'hoge',] ); // Failuresになるのは'hoge'だけ

Slide 42

Slide 42 text

© 2012-2024 BASE, Inc. #phpconfuk 新しく追加された アサーション、オプション 42 ● assertObjectNotEquals ○ オブジェクトに定義済みのメソッド(デフォルトはequals())の返り値同 士で、厳密比較(===)して一致していないことを検証する asString() === $other->asString(); } } assertObjectNotEquals($a, $b); // True $this->assertObjectNotEquals($a, $c);

Slide 43

Slide 43 text

© 2012-2024 BASE, Inc. #phpconfuk 新しく追加された アサーション、オプション 43 ● --exclude-filter ○ --filterオプションの除外バージョン ○ パターン(ファイル名やテスト名など)に一致したテスト以外を 実行する ● --list-test-files ○ 実行できるテストファイル一覧を表示する

Slide 44

Slide 44 text

© 2012-2024 BASE, Inc. #phpconfuk 最後に 44 今回どのChangeLogに触れたかは、スライドの最後に載せています。 時間の都合で一部のみの解説になりましたが、解説していない機能や変更があります! ● xml形式の構成ファイルについての変更 ● getMockBuilderが消えそうになった話 ● TestCaseクラスで多くのメソッドにfinal / protected修飾子がついた 前回のPHPUnit 10概論の話を含め、「PHPUnit10(または11)で非推奨になって、 PHPUnit11(または12)で使えなくなる」の機能がたくさんあると感じました。 バージョンを上げる作業をする時に書き直す作業が減るきっかけにもなるので、 将来的に使えなくなる書き方は、避けたほうが無難ですね。(自動置換ツール欲しい)

Slide 45

Slide 45 text

© 2012-2024 BASE, Inc. #phpconfuk 最後に バックエンド エンジニア SRE フロントエンド エンジニア セキュリティ エンジニア QA エンジニア データ エンジニア etc… We are hiring! https://binc.jp/jobs

Slide 46

Slide 46 text

© 2012-2024 BASE, Inc. #phpconfuk 今回触れたChangeLog 46 PHP 8.2以上が必須に ● #5101: Support for PHP 8.1

Slide 47

Slide 47 text

© 2012-2024 BASE, Inc. #phpconfuk 今回触れたChangeLog 47 テストスタブでexpectsが非推奨に ● #5535: Configuring expectations using expects() on test stubs

Slide 48

Slide 48 text

© 2012-2024 BASE, Inc. #phpconfuk 今回触れたChangeLog 48 TestCase / MockBuilderクラスのメソッドがいくつか非推奨に ● #5214: TestCase::iniSet() (this method was already soft-deprecated in PHPUnit 10) ● #5216: TestCase::setLocale() (this method was already soft-deprecated in PHPUnit 10) ● #5240: TestCase::createTestProxy() (this method was already soft-deprecated in PHPUnit 10) ● #5241: TestCase::getMockForAbstractClass() (this method was already soft-deprecated in PHPUnit 10) ● #5242: TestCase::getMockFromWsdl() (this method was already soft-deprecated in PHPUnit 10) ● #5243: TestCase::getMockForTrait() (this method was already soft-deprecated in PHPUnit 10) ● #5244: TestCase::getObjectForTrait() (this method was already soft-deprecated in PHPUnit 10) ● #5423: TestCase::returnValue(), TestCase::onConsecutiveCalls(), TestCase::returnValueMap(), TestCase::returnArgument(), TestCase::returnSelf(), and TestCase::returnCallback() (these methods were already soft-deprecated in PHPUnit 10)

Slide 49

Slide 49 text

© 2012-2024 BASE, Inc. #phpconfuk 今回触れたChangeLog 49 TestCase / MockBuilderクラスのメソッドがいくつか非推奨に ● #5305: MockBuilder::getMockForAbstractClass() (this method was already soft-deprecated in PHPUnit 10) ● #5306: MockBuilder::getMockForTrait() (this method was already soft-deprecated in PHPUnit 10) ● #5307: MockBuilder::enableProxyingToOriginalMethods(), MockBuilder::disableProxyingToOriginalMethods(), and MockBuilder::setProxyTarget() (these methods were already soft-deprecated in PHPUnit 10) ● #5308: MockBuilder::allowMockingUnknownTypes() and MockBuilder::disallowMockingUnknownTypes() (these methods were already soft-deprecated in PHPUnit 10) ● #5309: MockBuilder::enableAutoload() and MockBuilder::disableAutoload() (these methods were already soft-deprecated in PHPUnit 10) ● #5315: MockBuilder::enableArgumentCloning() and MockBuilder::disableArgumentCloning() (these methods were already soft-deprecated in PHPUnit 10) ● #5320: MockBuilder::addMethods() (this method was already soft-deprecated in PHPUnit 10)

Slide 50

Slide 50 text

© 2012-2024 BASE, Inc. #phpconfuk 今回触れたChangeLog 50 コメント(アノテーション)を使用したメタデータが非推奨に ● #4505: Support for metadata in doc-comments

Slide 51

Slide 51 text

© 2012-2024 BASE, Inc. #phpconfuk 今回触れたChangeLog 51 dataprovider周りの仕様変更 ● #5100: Support for non-static data provider methods, non-public data provider methods, and data provider methods that declare parameters ● #5225: Allow providing named arguments from a data provider

Slide 52

Slide 52 text

© 2012-2024 BASE, Inc. #phpconfuk 今回触れたChangeLog 52 新しく追加されたアサーション、オプション ● #5629: --exclude-filter CLI option for excluding tests from execution ● #5642: --list-test-files CLI option to print the list of test files ● #5600: Assertions for comparing arrays while ignoring a specified list of keys ● #5811: assertObjectNotEquals()