この記事はGRIPHONE Advent Calendar 2019 16日目の記事です。
TDD(テスト駆動開発)をしたい、けど、テストを書かずに実装しちゃった。そんな経験ありませんか?
今回はTDDの導入についてではなく、チームでのテストを書く文化を根付かせるための工夫を紹介したいと思います。
はじめに
TDD開発をしている人からしたら、TDD開発をするんだったら、必ずテストを書くでしょって思うかもしれません。おそらくそうだと思います。
ただ、テストを書くことのがめんどくさい、あるいはテストよりも先に実装したい、実装したけどテストは書いてなかった、テストを書く工数が確保できてない、動けばええやん、などの理由があってテストを書くのに抵抗がある人がいるかもしれません。
そこで、今回の記事では、まずはテストを書かせる文化を作るための工夫をしてみた、という紹介記事になります。
これからTDDをチームでやるよって方はこの記事はスキップしていただいてもいいのかなと思います。
また、テストを書くようにする、ということはテストのカバレッジを上げる、ということだと考え、本記事ではテストのカバレッジを上げることを目指すことにします。
テストのカバレッジを上げるということについて
テストのカバレッジを上げることとはどういうことなのかをまとめておきたいと思います。
メリット
- 気軽にコードの修正ができる(テストがなくて動いているコードには触れない方が良いと考えてしまう)
- 再設計・リファクタリングしても影響範囲がわかる(テストがコケるため)
- 仕様変更に強くなる(仕様は変わるもの)
- テストがコードリーディングの手助けになる
- コードに自信が持てる
- 品質の見える化がされる
注意点
ただ、注意点としては、「カバレッジが上がる=コードの品質が上がる」わけではなく、上記で書いたメリットにもあるようにリファクタリングに強くなったり、仕様変更に強くなったりすることで、間接的にコードの品質が上がると信じています。
上のスライドで和田さんも仰っていますが、テストを書く時間がないのではなく、テストを書かないから時間がなくなるのです。
過去事例
ちょうど今月の1日に東京の大田区で行われた第20回目のPHPカンファレンス2019でも、吉田あひるさんより以下のように「5ヶ月でカバレッジを20%から90%にした話」の講演がありました。
私もこの講演を聴いていました。カバレッジとアプリケーションの品質は必ずしも比例することはないですが、以下のようなメリットはあります。
- 気軽にコードの修正がしたい
- コードリーディングのコストを下げたい
私もこれには賛同したいし、似たような理由があり、今回のチーム開発でカバレッジの見える化をさせていただきました。
また、同じサイバーエージェントグループ内のゲーム会社である株式会社グレンジでも似たタイトルの発表がありました。
こちらもカバレッジを90%以上にしたとのことです。このスライドでも書いてあるように、テストがあることでリファクタリングがしやすいなどのメリットがあります。
テストを実行する仕組み作り
やはりテストを実行するというのは、開発フローの中で自動でチェックさせたほうがいいのかなと思います。そこで、現在所属しているチームでは、git上でマージしたタイミングにテストを実行しています。また、マージする前も環境にデプロイ時にもテストを実行しています。
gitにプッシュ(マージ)されたらAWS CodeBuildを用いてテストが実行され、その結果がslackに通知される。このようにすれば、必ず機能開発を完了時(マージ時)にはテストコードがチェックされます。また、テストが失敗したら開発環境のデプロイが失敗するようにすることで、テストコードがチェックする範囲内では品質の保たれたものがデプロイされることになりますね。
カバレッジの見える化をする
テストの結果をslackに通知するだけでは、人間なのできっとその通知をスルーすることがあるかもしれないです。また、テストコードがしっかり書かれているのか、このテストを書いたことでどのくらいカバレッジが増えたかなどがわかるとよりテストを書くというモチベーションが上がると思います。
そこで、カバレッジを計算したいと思います。ここで使用する言語はPHPで、コードカバレッジ解析ができるphpunitを使用したいと思います。また、今回はXdebug拡張モジュールが提供するステートメントカバレッジ機能を利用するため、Xdebugのインストールもしておく必要があります。
参考:https://phpunit.readthedocs.io/ja/latest/code-coverage-analysis.html
解析方法
カバレッジの計算は以下のようなコマンドで実行することができます。
$ phpdbg -qrr phpunit --coverage-html coverage
また、–coverage-htmlをつけることで、解析結果をhtmlに出力してくれるようになります。そのHTMLを開くと、以下のようにわかりやすくカバレッジが見えるようになります。
このように、ディレクトリごとにLines(行単位)、Functions and Methods(関数単位)、Classes and Traits(クラスやtrait単位)でのカバレッジを見える化してくれます。
ControllerとLogicのテストを分ける
現在のチームではControllerとLogicの2種類のテストを書いているのですが、ここで気をつけないといけないのが、Controllerのテストを書くだけでLogicのカバレッジも稼げてしまいます。なので、ControllerではLogicについてはあまり追う必要はないと思い、それぞれ別々に考えたいと思います。
そこで、ControllerのテストをしたときのControllerだけのカバレッジ、LogicのテストをしたときのLogicだけのカバレッジを見える化することで、よりカバレッジという数値の精度を上げたいと考えました。
$ phpdbg -qrr phpunit tests/Controller/ --coverage-html coverage/controller
$ phpdbg -qrr phpunit tests/Logic/ --coverage-html coverage/logic
このように出力するHTMLを別々のディレクトリにすることで、それぞれのカバレッジを分離して結果を見ることが可能になります。
カバレッジの手軽に見える化
テストのカバレッジの見える化ができたらそれで終わりではありません。運用がコアです。そのカバレッジを見るコストというのはなるべく低くないと見てくれないと思います。例えば、カバレッジの確認をするためには、各々のPC上でテストを実行してHTMLを確認します、と言われたら、おそらく誰もカバレッジのチェックはしないと思います。そこで、以下のような構成を考えました。
上で紹介したslackへの通知と違うのは、phpunitの結果をHTMLに出力して、それをS3にアップする。そのHTMLをインターネットに公開することで、ブラウザで簡単にカバレッジを確認することができるようになります。マージをトリガーにして常に最新のカバレッジ結果を自動でアップしてくれるので、そのURLをブックマークすれば、簡単に最新のカバレッジをブラウザで確認できるようになります。
※もちろん、HTMLの公開をするときはS3上でIPの制限などの設定をして、社外からは見れないようにしています。
カバレッジの変化を追う・見える化
運用がコアということで、カバレッジがどのくらい上がっているのか、それとも下がっているのか、普段からそういう遷移を見れるようにならないと書くモチベーションが上がらないと考えました。そこで、S3のアップ時に、最新のカバレッジに上書くのとは別にタイムスタンプごとのディレクトリを作成してアップする、という工夫をしてみました。
このように、一番下のlatestというディレクトリにアップしつつ、そのときのタイムスタンプのディレクトリにHTMLをアップします。このようにすることで、タイムスタンプごとのディレクトリを見れば、その日付・その時間のカバレッジを確認することができます。すなわち、そこからカバレッジの遷移を知ることができます。
ということはグラフの作成を行うことができます。
ということで、例えばこのようグラフが出力することができました。このグラフを見ることで、
「おお、今回のテストでカバレッジが5%も上がったぞ!」
「やべぇ、カバレッジが下がってきている。。」
などを、パッと見で確認することができます。個人的な感想ではgithubに草を生やす感覚に近いんじゃないかなと思っています。
さいごに
このように、テストのカバレッジ見える化計画としてチームにテストの見える化をした結果、より前のめりにテストを書いてくれました。(というか、自分自身のテストを書くモチベーションがとても上がったと書いたほうが正しいかもですが。)
また、それのおかげか、カバレッジ見える化してからはTDDの文化がちょっとずつではありますが、根付き始めました!