どんなテストコードを書きたかったか
検証したいこと
<?php class Subject { public function getAsumikamKudamono(): array { // ... return [ 'ringo' => [ 'color' => 'red', 'kamu' => 'syaku', ], 'mikan' => [ 'color' => 'orange', 'kamu' => 'mogyu', ], ]; } }
上記のような配列が返ってくるとする。
この時、asumikamが好きな果物がちゃんと入っているか、というのをキー名のみ(ringo, mikan)で判定するようなテストコードが書きたいな〜となった。 (この時の観点としてringoやmikanが値として持っている配列自体は興味がないので)
取れる選択肢
assertArrayHasKey
を使う
<?php $expectedList = [ 'ringo', 'mikan', ]; $actual = $this->subject->getWorldKudamono(); foreach ($expectedList as $expected) { $this->assertArrayHasKey($expected, $actual, '必要なキーがない'); }
パッと思いついたのはassertArrayHasKey
だったが、これはキーが1つしか参照できないので、foreach
と合わせて使うという書き方。
ただ、テストコードにforeach
が入ると、若干ロジックが入っているみたいで嫌か??う〜ん、と考えて、こっちは採用しなかった。*1
array_keys
とassertEqualsCanonicalizing
の合わせ技
<?php $expectedList = [ 'ringo', 'mikan', ]; $actual = $this->subject->getWorldKudamono(); $actualKeys = array_keys($actual); $this->assertEqualsCanonicalizing($expectedList, $actualKeys, '必要なキーがない');
最終的にこの書き方を選択したが、果たして100点の回答なのかな〜🤔の顔になった。
array_keys
を使ってるし、可読性で言えば上の書き方の方が良いのかも。
assertArrayHasKeys
というひらめき
う〜んと考えていると「assertArrayHasKeys
が実はあるのでゎ・・・!?」と閃いた。
そこで、インターネットで調べてみると以下Issuesに遭遇した。
要約すると、マジで同じようなことを考えて「assertArrayHasKeys
が必要なのでゎ・・・!?」と閃いている方のIssuesだった。
Issuesの中身を見てみると「実装してみたぽよ〜」と提示している人もいる。
おお!?とおもって実際にPRを見に行ってみた
「マージしないことを決めたよ〜」か〜〜〜!!!なるほど〜〜〜!!!
理由が知りたいが、とりあえず、やはりそんなものはないという結論になった。
結局なんでassertArrayHasKeys
がないのかわからなかった&array_keys
とassertEqualsCanonicalizing
の合わせ技でよかったのだろうか〜(普通にもっといい感じの書き方ありそう)、という気持ちになったのであすみめもとしてブログに残しておこう〜。オワリ。
追記
id:o0h さんがリプライでめちゃくちゃ一緒に考えてくれた。 人と話すと自分の思考が整理されたり進んだりするので、反応もらえて嬉しかった。
某有名OSSさんでもそんな書き方してるな、こういうの見つけると少し安心するかもねhttps://t.co/0bRJywfUfx
— 今日も誰かのにちようび(おいしい鮭親子丼) (@o0h_) 2024年5月17日
別に正解でもなんでもないと思うけど!!
▲ Composerのテストでも同じような書かれ方をしているのを見つけてくれた(たしかにちょっと安心した、というか探し出してくるのすごいな)
あと、単に「テストのロジックの分かり易く」とは別の観点で「ウチらの大事にしてるコトぢゃね?」要素もあって良いと思っていて、
— 今日も誰かのにちようび(おいしい鮭親子丼) (@o0h_) 2024年5月18日
> 配列の見た目で、キーの部分だけ興味ある
これが「そのPJでは頻出」なら「扱っているドメインの力学がそうさせる」可能性→カスタムアサーション置いちゃえ!もアリ
▲ ドメインで頻出ならカスタムアサーションありかもね!(たしかに〜〜)
取り込まれないの、「あんまり使われる場面がないからか?」がいまのところの解...(個人の感想)
— あすみ (@asumikam) 2024年5月18日
このような配列の見た目で、キーの部分だけ興味ある、というユースケースが少ないのかな、と...(実際、いろんなもの詰め込み配列だからこそ取らなきゃいけない選択肢なのかなと...)
ちょいニッチっぽいassertionもあるしな〜とか思ったんですが(昨日時点)、
— 今日も誰かのにちようび(おいしい鮭親子丼) (@o0h_) 2024年5月18日
この返信を見て
a. ニーズが普遍的
b. 実現しようとすると複雑
c. 曖昧な挙動にならない
の{(a or b) and c}って条件で見るとどうか?って意味で
「aは強くなくbが弱い」→取り込まない、はアリそう〜〜〜って納得しました!
▲ なんで入らないんだろう〜の推測たち(メタ視点で何かを考えるのがうますぎる)
*1:今思えば、ifは明確にいやだが、foreachならそこそこ問題ない?