かなり時間が経ってしまいましたが、PHP Conference Japan 2019 にて登壇してきました。
20%もなかったカバレッジを90%まであげたので、そのためにしたことの話をしました。
動画はそのうちYoutubeに上がるのかな?上がったらこの記事に貼っておきます。
動画あげてもらいました!
www.youtube.com
この記事は登壇後記という体のただの乱文です。
ポエム
いやぁ、普通に疲れました。
登壇が終わってから、ブログを書いてる今この瞬間も完全に燃え尽きてます。
一つのエンドポイントにテストを追加するとだいたい0.04%〜0.08%くらいはカバレッジが上がってくれるんですが、 途中 0.01%〜0.03%しかカバレッジが上がらないみたいなことが連発していた時はだいぶ精神的に追い詰められました。
けどなんとか登壇までに90%まで上げることが出来てよかった。
カバレッジをあげたかった理由は登壇の最初でも話したんですが、それ以外にも 「テストがあれば防げたようなバグを僕がデプロイしてしまったから」ってのがあるんですよね。
C0レベルのテストでも防げたようなしょうもないバグで、でもめちゃくちゃ重要な機能にバグを放り込んでしまって めっちゃくちゃ情けなかったんです。
この情けないミスの償いと、同じミスを僕以外のエンジニアにさせないためにカバレッジを上げなければと強めに決心しました。
コツコツと自分の関わった範囲にテストを追加していくような手段も取れたんですけど、 派手にカバレッジを上げ、それをネタに登壇することで広報的な効果も追加出来るんじゃないかなーと思って、一気に90%まで上げることにしました。
ほら、テストってただでさえユーザーに対して直接価値を届けられるようなものではないじゃないですか。(主観)
なので、テストに大きくリソースを割くことに抵抗というか葛藤があったんですが、広報的な効果を追加すれば会社的なメリットも増えるし、まぁいいんじゃないかなーと。
ですが実際に登壇した結果、広報的な役割をしっかり果たせたのかというと
- ポジティヴな印象を与えることが出来たのかわからん
- PHP界隈の話題にすることが出来なかった
という点でかなり微妙なところではあるので、もうちょっと技術的に面白い話が出来たらよかったかなぁという反省があります。
カバレッジを上げて得たもの
チームメンバーへの感謝の心
僕がテストを書くことだけに集中出来るようにチームメンバーのみなさんがだいぶ気を使ってくれたので、本当に感謝しています。
具体的には、ほぼフルリモートで働くことを許可してくれたり、なるべく僕にテスト以外の作業が発生しないように配慮してくれたりですね。
みんなの配慮がなければ絶対に登壇までに90%は間に合わなかったと思います。
この場を借りてお礼を言います。ありがとうございました。
デプロイの安心感
C0レベルのテストは90%の箇所に書かれているので、とりあえず正常系であればテストが通っていればほぼほぼ動くのではって感じです。
ただ、実装をみて仕様を想像しながらテストを書いてるだけなので、漏れてるケースはちょこちょこありそうだなー。
カバレッジを追い求めることの無意味さ
おい!!!!!!!って感じなんですけど、カバレッジを追いかけるのはマジで虚無だなという感想を得ることが出来ました。
あ、いや、今回カバレッジを上げたが無意味だったという話ではないです。念の為。
今回カバレッジを上げたことは大きな意味がありました。が、カバレッジをKPIにする必要はないなという話です。
登壇の最中にも軽く話したんですが、弊社のサービスの場合は75%や80%を超えたあたりでだいたい必要そうな箇所にはテストをかけたなーという感覚があって、 それ以降は登壇のタイトルで90%って言ってしまったから仕方ねぇって感じで、「書かなくてもいいかなー」って感じのユニットテストをもりもり追加するような感じになっていました。
おそらくサービスごとに適切なカバレッジがあって、それは必要な箇所にテストを書いた結果自然と導き出されるものなので、カバレッジをKPIにしてテストを書いていくと不必要なテストが発生するんじゃないかなと思います。
みんなカバレッジとか気にせずにちゃんとテスト書いていこうな。
とはいえ、ローカルのPHPを7.4にあげてみた時にバグを発見してくれたのは「このテスト書かなくてもいいんじゃないかなー」って思って書いたユニットテストだったりしたので「このテストは必要ない」って判断するのめっちゃむずいよねって感じなんですが・・・。
また別の話ですが、テストは最終的には負債でしかないっていう意見もあって、僕も割と共感してます。
PHPは動的型付言語だし型の制約が強いわけではないしって理由でテストを書かないという選択をするのはだいぶ難しいと思うんですが、テストを書かなくて良いようなコードをかけたらよいなぁと思ってます。
PHPStanやPhanという静的解析がだいぶ強くなっているので部分的には可能かなぁ、どうだろう。
テストの責務についての考え方
Unitテストや機能テスト、受け入れテストでそれぞれのテストが担保すべき内容って違うんですよね。
機能テストで実行されているコードはUnitテストが必要ないのかというと絶対にそんなことはなくて、
テストの関心ごとが違うからそれぞれテストしないといけないと思うわけです。
機能テストの関心ごとじゃないところまで機能テストで担保しようとするとテストが大きくなりすぎちゃいますしね。
漠然と今までも理解していたんですが、今回死ぬほどテストを書きまくった結果そこらへんの考えがより明確に(深く?)なったので、どこかで改めてまとめたいなーと思ってます。
おわりに
はい、こんな感じかなー
テストは書いたので、次はこのテストたちを武器にリファクタリングに励みたいと思います。
おわり