#あすみかんの上にあすみかん

#たのしいことしかかかないことをここに決意します

PHPUnitで「特定のキーたちがあること」をいい感じに書きたかった(assertArrayHasKeys)

どんなテストコードを書きたかったか

検証したいこと

<?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_keysassertEqualsCanonicalizingの合わせ技

<?php

$expectedList = [
    'ringo',
    'mikan',
];

$actual = $this->subject->getWorldKudamono();
$actualKeys = array_keys($actual);

$this->assertEqualsCanonicalizing($expectedList, $actualKeys, '必要なキーがない');

最終的にこの書き方を選択したが、果たして100点の回答なのかな〜🤔の顔になった。

array_keysを使ってるし、可読性で言えば上の書き方の方が良いのかも。

assertArrayHasKeysというひらめき

う〜んと考えていると「assertArrayHasKeysが実はあるのでゎ・・・!?」と閃いた。

そこで、インターネットで調べてみると以下Issuesに遭遇した。

github.com

要約すると、マジで同じようなことを考えて「assertArrayHasKeysが必要なのでゎ・・・!?」と閃いている方のIssuesだった。 Issuesの中身を見てみると「実装してみたぽよ〜」と提示している人もいる。

おお!?とおもって実際にPRを見に行ってみた

github.com

sebastianbergmannさんの回答

「マージしないことを決めたよ〜」か〜〜〜!!!なるほど〜〜〜!!!

理由が知りたいが、とりあえず、やはりそんなものはないという結論になった。

結局なんでassertArrayHasKeysがないのかわからなかった&array_keysassertEqualsCanonicalizingの合わせ技でよかったのだろうか〜(普通にもっといい感じの書き方ありそう)、という気持ちになったのであすみめもとしてブログに残しておこう〜。オワリ。

追記

id:o0h さんがリプライでめちゃくちゃ一緒に考えてくれた。 人と話すと自分の思考が整理されたり進んだりするので、反応もらえて嬉しかった。

github.com

▲ Composerのテストでも同じような書かれ方をしているのを見つけてくれた(たしかにちょっと安心した、というか探し出してくるのすごいな)

ドメインで頻出ならカスタムアサーションありかもね!(たしかに〜〜)

▲ なんで入らないんだろう〜の推測たち(メタ視点で何かを考えるのがうますぎる)

*1:今思えば、ifは明確にいやだが、foreachならそこそこ問題ない?