「PHPUnit」に関する日記

次>

PHPUnit

ここTGWSで使っているテストツールのPHPUnitをバージョン9から10に上げました。
以前11に一気に上げようとして、必要な変更のあまりの多さに撃沈してしまったのですが、10までならひとまず大きなトラブルもなくスムーズに移行できました。
まあ、そのスムーズさで300ファイルほど修正が必要だったんですけどね。
ほとんどが機械的な置き換えで済むシンプルなものだったので、普通の置換やコピペで済ませました。
最近はAIエージェントとかもありますが、変なところで独創性を発揮しちゃうことが少なくないので、AIに求めるのは助言程度にして、今回は自分で作業をしました。

アンパンマンDBとXdebug

アンパンマンDB(記事更新)

コラムからの転記。
この程度なら毎日いっぱいやってもいいのにね。

アンパンマンDB(システム)

リストをNULL検索できないバグを修正しました。
ただ、今のところ、何もない項目はNULLじゃなくて空文字列が入っているので、実質的に影響はありません。

Xdebug

Xdebug - Debugger and Profiler Tool for PHP
Xdebug導入しました。
すなわち、Xdebug使わない縛り辞めました。

もともとデバッガとしては、PHP標準のphpdbgを使ってました。
PHPUnitのカバレッジもphpdbgだったんですが、PHPUnit10以降(最新版は11)には使えなくて、phpdbgのために古いのを使う続けるのも厳しいなって思ってました。

カバレッジ計測の選択肢としては、PCOVもあったんですが、あんまり更新されてなさそうだったし、カバレッジ「だけ」というのもどうかと思ったので、デバッグ並びにカバレッジ計測の定番、Xdebugを導入した次第です。

そもそもXdebugを避けてphpdbgを使っていたのは、XdebugはPHP標準に入っていないというのと、カバレッジ計測が遅いという話を聞いたからだったのですが、実測してみると、今はXdebugのほうがphpdbgより1割ほど早く終わりました。

アンパンマンDB

アンパンマンDB(記事更新)

昨日のふくろうおじさんの流れで今度はおじいさんを追加しました。

こっちはコラムから転記組。
元気倍率アップ系ですね。
300より200のほうが見た目豪華なのがポイント。

アンパンマンDB(システム)

テストが不安定な問題、直接の原因は一応わかりました。
エラーコード0xC0000005(-1073741819)、アクセス違反です。
アクセス違反なら何でもこのエラーが出るので、このエラーコード一つで真の原因の特定はできません。
傾向として、カバレッジ計測なしだとエラーは起きず、計測ありのときだけエラーが出ることがあるので、カバレッジと何かの競合だと思われます。
落ちる部分のコードがやってることと言えば、同じPHPスクリプトを条件を変えて2回呼び出していることなので、ここで何らかのロックがかかってしまってカバレッジを邪魔しているのでは?と考えています。
完全解決までは、カバレッジ計測の頻度は減らすかなぁ。

アンパンマンDB

アンパンマンDB(記事更新)

おそらく1話限りのゲストだと思いますが、追加しました。
こういうのって、たまたま見かけたときに書いておかないと忘れますからね。

アンパンマンDB(システム)

本番環境では多分問題ないんですが、なんだか自動テストが不安定になっています。
最後までテストせず、エラーも出さず、急にすっと終わる感じ。
一応突然終了する地点は絞り込みましたが、別に何でもないテストをやっているようにしか見えないところなんですよね。
毎回発生するわけでもなく、なんだか不気味です。

PHPUnit

PHPUnit自体の機能とは特に関係ないんですが、うちのサイトの自動テストでは、HTMLの表示とかのテスト(結合テストに近いところ)もある程度やっていて、出力結果の保存とかもやっているんですね。
テストやるたびに、たとえ何の変更もなくて何の問題もなくても、何百ページ分ものHTMLファイルが出来上がります。
たとえ何の変更もなくて何の問題もなくても、改めて毎回テストをやること自体は、回帰テストといって、とても有意義なのですが、回帰テストは正しいか正しくないかだけわかれば充分なので、何が出力されたかまで細かく残す必然性はありません。
とはいえ、たとえ何の変更もなくても問題が起きることがあるから、回帰テストが必要なわけで、回帰テストに落ちたときだけは、何がおかしくなったのかを残す必要があります。
なので、普段邪魔になるからと言って、一律で保存をやめるなんてことはしないほうがいいでしょう。
だからといって、テストに落ちたときだけ保存するという器用なこともなかなか難しいわけで。
ということで、出力結果を破棄するオプションを作って、それをON/OFFすることで、保存するかどうか切り替えるようにしてみました。

GitHub Actions

動くようになりました。
Composerのバリデーションは神経質すぎるところがあるので実行しないことにして、本当にやりたい自動テストだけにしました。
phpdbg使えなかったけど、普通にPHPUnitを動かすだけでカバレッジは取れました。
アーティファクトがばらばらのファイルじゃなくてZIPアーカイブしかなさそうなので、HTML出力したカバレッジレポートを見て回ることはできないけど、まあ手元でZIP展開すれば見られるのでこれはまあOK。
あとは…そう、もういらなくなったCircleCIとの連携を切るだけ。

PHPUnit

ちょっと前からテストが動かなくなっていたので、ちょっと修正していました。
ちょっと修正というにはちょっといろんなところを調べまわってちょっと大変だったのですが。
で、最終的に何が悪かったのかというと、ネットの疎通確認に確実に存在するURLとして http://example.com/ を使っていたら、https://example.com/ にリダイレクトされていて、httpの方に繋がらないぞという判定になっていたことでした。

大変だったのは、それを突き止めるために別ソフトの修正を行ったら、修正が何も反映されず古いビルドが使われ続けたこと。
こっちは、修正が反映されなくなり始める前のバージョンまでソースを差し戻して、そこから新たに修正し直しました。
こういうのをどうにかできるのはGitなどバージョン管理システムのいいところですね。

アンパンマンDBとPHPとドラゴンクエスト10のプレイヤーイベントを検索および通知するサイト

アンパンマンDB(記事更新)

キャラ「ロボリィ」を更新
ゲスト声優が発表されたので、追記しました。

PHP8.2

切り替えました。
今のところ致命的なエラーは起きていませんが、PHPUnitがバージョン足りなくてテストできなかったり、DEPRECATEDが思ってもみなかった場所で出たりして、対応をしていました。

ドラゴンクエスト10のプレイヤーイベントを検索および通知するサイト

プレイベの通知メールです。
普通は一般ユーザー(閲覧者)が見るところではエラーはログにだけ残して非表示にしているのですが、メールが対応漏れてました。
今は修正完了しています。
こういうの、日記で事後報告じゃなくて、ちゃんと告知できるような仕組みも必要かなぁ。

アンパンマンDB

更新履歴管理が動かなくなっていたので修正していました。
PHPに型宣言がなかったころからアンパンマンDBがあって、その頃はドキュメントコメントで型を書いていたのですが、実は管理画面ではこれを守っていなかったんですね。
で、PHPのバージョンを上げて、型宣言が正式にできるようになったので、コメント通りの型を指定したら、というわけです。
こういうの、自動テストをちゃんと書いていれば見つかる類のものですし、実際、修正の際には自動テストを書きました。

今、TGWS全体で、テストが必要なコードのうち、実際にテストできているのは54%。
残りの46%は、何かが起こっても自分で見に行くまでは何もわからないのです。
やはり、カバレッジ(コード網羅率)を上げていかねば。

カバレッジ

カバレッジのグラフ
サイズがでかいので画像は直接貼りませんが、カバレッジの推移のグラフを表示する機能を作ってみました。
昨日紹介したRindow Math Plotは、ファイルへの保存は対応しているように見えて事実上対応していなかったので、直接表示するページを管理画面に作りました。
横軸はカバレッジ記録開始した日からの経過日数にして、上下に並べて時系列で傾向を見られるようにしました。
新機能を実装して複雑性が上がるとカバレッジが下がり、複雑性が上がらない間はテスト作成を頑張ったりしているのでカバレッジは上がる傾向があります。
今、日記の内部挙動を変えようと思っていて、内部挙動を変えても外部仕様が崩れないことを保証するために、日記の、特に管理画面のテストの作成を頑張っています。

アンパンマンDB(みんなのタグ)とFlaky test対策

アンパンマンDB(みんなのタグ)

構想段階で全く着手していないアイディアなんですが、「共起度」というもの。
このタグとこのタグは一緒にいることが多いなってやつ。
これの統計を取っておいて、みんなのタグの編集画面での並び替えに活かしたいなと。
例えば、すでに「姫」のタグが付いていた場合、共起することが多い「女」を上の方に表示するとか。
「共起度」というのはわかりにくいから、「関連度」とかの用語にした方がいいかもしれないですね。

Flaky test対策

新VPSに移行してからはなぜか落ち着いているんですが、不安定なテストの対策。
ネットワーク関係など、プログラムが正しくても失敗してしまうテストがあります。
プログラムが正しいならそんなもの無視すればいいんですが、Flaky testだと思っていたものが実はプログラムミスだったということもざらにあるので、ネットワーク関係だからエラー無視、というわけにもいきません。
今のところ、毎回エラーの詳細を出力して、目視確認して、「これは今回だけの偶然だな」とか判断しているのですが、頻度が高いと面倒だし、精神衛生上もよくありません。
で、なんとかFlaky testを自動検出して、あるいはそうでなくとも、FlakyとわかっているテストはFlakyなりの判断基準を持たせて、ただFlakyなだけなら一応テスト成功として扱いたいなと。
実現するには、過去数回のテスト結果を保存しておいて、一定割合までの失敗なら許容する、くらいの扱いが現実的かと考えています。

参考:世界中のITエンジニアが悩まされている原因不明でテストが失敗する「フレイキーテスト」問題。対策の最新動向をJenkins作者の川口氏が解説(後編)。DevOps Days Tokyo 2022 - Publickey

PHPUnit

ちゃんとクラスになっている部分はテストできるのですが、サーバーから呼び出されるPHPファイルに直接あれこれ書いているものは、なかなかテストしづらいのです。
ちゃんと「呼び出すファイル」と「ロジックを書いているファイル」を分けていればいいのですが、小さいプログラムを手っ取り早く実行できるようにしようとすると、やっぱり呼び出すファイルに直接書いた方が早いし解りやすかったりするのです(Hello Worldするためだけにフレームワークのあちこちを飛び回るようなプログラムは書きたくない)。
こういうのをなんとか自動テストの仕組みに乗せるにはどうしたらいいかと考えたのですが、結局テストって入力に対する出力を見るだけなので、入力に使う変数($_POSTなど)を差し替える、出力をバッファリングして捕まえる、というのがある程度の落としどころかなと考えています。

PHPUnit


テストコードを書いていない部分が多いものの、ゼロからテストコードを書く部分はしんどすぎるので、全部の機能に対して、テストの最初の一歩となるテンプレートを作ってみることにしました。
テンプレートのままでは未完成なテストなので、Incompleteばっかり出ますが、逆に言えば、このIncompleteを手掛かりにテストを作っていけばいいということになります。

PHPUnit

PHP8.1に上げたらエラーがいっぱい出たというのも、CIが落ちるようになったのも、テストが充分であればある程度防げたはずのことだったのです。
ということで、自動テストのカバレッジを上げる方向で、クローリングではテストできない編集機能周りを中心に、テストコードを増やしていこうと思います。

PHP8.1

とりあえずエラーが取れたので、CIが落ちる方を暫定対応。
落ちるテストをしなくしたというだけの、本当に解決にならない対応なんですけどね。
テストしなくなった対象のコードを使わなくする方向で根本対応を検討中です。

PHP8.1

開発環境でもテストプログラム自体が落ちる件を再現できました。
どうやら、アンパンマンDBの古いコードのカバレッジを取ろうとしていると、落ちるようです。
まあ、新たに開発することがない以上、継続的にテストをしても仕方がないと言えばないのですがね…ただテストをなくして落ちなくするより、古いコード自体をなくしてそもそもテスト不要にするのが正攻法だと思われます。
放置案件になりかけてる新管理画面にいよいよ着手せねば…。

PHPUnit

カバレッジの変遷を自動で記録する仕組み作成中。
カバレッジが高いと、ある程度網羅的にテストができている証拠なので、高めておきたいのですが、何も考えずに開発していくとどんどん下がるんですよね。
下がっているのに気付いて対策を講じたり、上がっていくのを見て喜んだりなど、変遷を残しておくと、何かと使えると思うのです。

PHPUnit

アンパンマンDB4やらなんやらで、ページを目視確認しながらもりもり開発していった結果、自動テストのカバレッジが著しく下がってしまいました。
カバレッジが高いからいいコード、なんて都合のいいことはないのだけれど、自動テストをもれなく書いていると、予期せぬデグレとか、外部サービスの仕様変更とか、確認したつもりでできていなかった部分とか、結構見つかるものなのです。
で、外部サービスの仕様変更で使えなくなった機能の削除とか、目視ではいい感じに動いているように見える機能のちゃんとしたテストとか、やってました。
そして、ちゃんとテストした機能なら、当初考えていた意外にも使い道がありそう…ということで、何か考えています。

Change Risk Anti-Patterns (CRAP) Index

またPHPUnitの話題だけれども、CRAPインデックス。
コードの複雑性を評価したもので、でかいほどヤバい(悪い意味で)。
で、これの大きいメソッドをコードカバレッジのダッシュボードから見ることができるんだけれども、実際見てみたら、触れたくないカオスなコードが…。
気合いのあるときになんとかしよう。

PHPUnit


今更ながら、カバレッジ出すようにしてみました。
決して良くはない数字だし、PHPUnitの対象にしていないコードは根本的にカバレッジの対象にもならないけど、まあ、最初はこんなもんかな。
ほとんどロジックがなくてテストするまでもないテンプレート的なPHPファイルも多いので、うまい事分けてカバレッジ上げていきたいものです。

次>