基盤チームに所属している @okinaka です。
個人的には CakePHP とは長い付き合いで、もう14年以上になります。 BASE の事業においても10年間ずっと支えてくれている大変ありがたい Web フレームワークです。
以前から BASE の多くのコードはまだ古い CakePHP 2 (v2.10.24) 上で動作していることが課題になっています。 CakePHP 自身は順調に開発が継続されていますが、2系から3系へのバージョンアップはなかなか困難で二の足を踏んでいました。 そうこうしているうちに古いバージョンの2系は既に公式でのサポートは切れているうえに PHP 8.0 未サポートの状態です。
さすがにそのまま継続して利用するのは無理があるので、数年前から、より柔軟にシステムを構築するためのアーキテクチャ再設計をすすめています。
その成果は上がってきているのですが、単純なフレームワークのバージョンアップにとどまらず、根本的なアーキテクチャを再設計しているところなので、全てが刷新されるまでには、まだまだ既存の仕組みを利用することが続きそうです。(アーキテクチャの再設計に関しては、プラットフォームチームが別の機会で紹介することになると思います。)
さぁ、大変。PHP 7.4 の EOL (2022-11-28) も迎えて、もう後のない状態、このまま先に進むには PHP 8.0 以上に上げる必要に迫られてきました。
PHP 8.0 でも意外と動くよ
ありがたいことに、CakePHP 2 を公式のリポジトリからフォークして PHP 8.0 対応されている方がいることを CakePHP の Slack チャンネルで知りました。
お試しでやってみたら、すんなり動くではありませんか!いける!と思ったのですが、一つだけ問題がありました。 それは自動テストは、未対応なのでした。
ということで、PHP 8.0 で動作するために必要な PHPUnit 9 対応を独自にやってみたらできたという報告です。
PHPUnit 9 に対応してみる
前置きが長くなってしまいましたが、本題に入ります。
PHPUnit 9 は PHP 7.3 以上に対応していますので、いきなり PHP 8.0 まで上げる必要はありません。 今回は公式の CakePHP 2.10.24 (& PHP 7.4) のままで PHPUnit 9 に対応してみます。
大きな要点は2点あります。
- CakeTestCase や ControllerTest を継承しない (あるいは差し替える)
cake test
を使わずに直接 PHPUnit を実行する
他にも細かなポイントはたくさんあるのですが、さらに長くなりそうなので以上で留めておきます。
CakeTestCase や ControllerTest を継承しない (あるいは差し替える)
とても残念なことですが、PHPUnit のバージョンアップ(phpunit>=8.0)に伴い後方互換性のない変更があったため、CakeTestCase や ControllerTest を継承してテストを書くことはできなくなりました。
TestCase の setUp()
や tearDown()
などのメソッドの戻り値に型宣言が追加されたためです。
こればかりは、フレークワーク側を修正するしかないので、応急措置として CakeTestCase をコピーしたクラスを用意しました。
名前空間がなく、独自のクラスローダーを利用しているメリットを活かし、app/TestSuite/CakeTestCase.php
を配置することで、App::uses('CakeTestCase', 'TestSuite');
と書かいていると、オリジナルではなくコピーの方が読み込まれます。
対応例はこちら。
直接 PHPUnit を実行する
CakePHP 2 では、cake test
というコマンドが用意されていて、内部では PHPUnit を動かしています。 古いPHPUnit 向けのロジックが書かれているため、これを使うことを避けて PHPUnit を直接実行します。
弊社では、バージョンアップ以前から PhpStorm などの IDE の支援を受けるために PHPUnit を直接利用したいという理由で対応してました。 そのための対応方法は GitHub の issue に弊社の tenkoma さんが紹介していますので参考になります。
テストコマンド起動時のおまじない少々とフィクスチャ周りのロジックの追加が必要でした。
なお、CakePHP 2 には web 上からテストを実行する機能があるのですが、その機能は切り捨てることになります。(IDE や CI でテストする分には不要なのでなくても困らないと思います。)
対応例はこちら。
サンプル
今回のブログのために、CakePHP 2 で PHPUnit 9 を動かすサンプルを作成してみました。 CakeTestCase のためのテストケース (CakeTestCaseTest) を用意しました。GitHub Actions の workflow を使って自動テストにも対応しています。
おわりに
本来、フレークワークは常に最新バージョンを使うことが好ましいことなのですが、自動テストがあれば、古いバージョンを使っていても安心できると思います。 (あくまで移行完了までの中継ぎとしてですが)
この記事で、CakePHP のバージョンアップができずに古いバージョンを延命しようかどうか迷っている方に参考になれば幸いです。