スローテストを解消する12の方法
みなさんこんにちは。@ryuzeeです。
システム開発において一番コストが高いものは人的リソースであることがほとんどです。 したがって開発者の時間効率をあげるためにできることは色々と取り組む必要があります。 例えば個人の開発マシンが遅くてビルドやテストに時間がかかるとかもっての他です。 一日10回ビルドして一回のビルドに5分かかるとします。 これを高性能なマシンに変えたら2分になったとすると、(5-2)1020=10時間。 時間単価5000円として一ヶ月あたり合計50000円の節約になります。 同じことがCIやテスト自動化にも言えます。
CIサーバのハードウェアを高性能なものに変更する
会社のあまったPCを使ったりして遅いテストを待つのはバカバカしいの一言だ。
CIサーバを複数台で構成する
上の話と同じような話。Jenkinsは複数台構成を取ることができるし、多分他のCIも同様だ。
CIサーバのディスクをSSDに変更する
ディスクのIOがボトルネックになるケースもある。サーバのスペックが良くてもハードディスクのIOはやはり遅いので、SSDに変えることによって高速化できる。場合によってはテストの所要時間が1/5から1/10になるケースもある。
テストで利用するデータベースをインメモリDBにする
上の話と似ているが、テストケースのsetUpで大量のデータをデータベースに登録するような場合どうしてもテストの実行に時間がかかるようになる。これをインメモリDBに変えることで高速化が可能だ。
テストスイートを分割する
コミット時に実行するテストと結合テストや受け入れテストを分離する。テストをグループ化しておき、必要なグループ単位で実行できるようにする。たとえばSCMへのコミットの際にユニットテスト群を毎回実行し、ユーザー受入試験などのテスト群はユニットテスト群が正常に通った場合のみに動かす、定時で動かすなどの工夫もできる。
データベースを利用する箇所をモックに変える
データベースを利用するテストには時間がかかる。ユニットテストレベルでは一般的に外部のリソースと結合していないことを前提とした方が良いので、モック等に差し替えることを検討する。
外部システムとの連携テストの箇所をモックに変える
同上。外部のWebサービスやAPIとの連携のテストについても、モックを用意してそのテスト単体で動作するように依存性を排除していく。これによって外部システムの状態によってテストが落ちる/落ちないが変わるといった状況からは解決もする。
テストで利用するデータベースを最小データに保つ
自動テストを行う際にデータに本番データベースのコピーを使うのは最悪のアプローチだ。そうではなく、最低限のデータセットを用意し(fixture)、それを各テストで共通して使うようにする。共通部分以外のデータについては別で管理してテストケース毎に個別に呼び出すか、またはデータベースを然るべき状態に変更するためのAPI等を用意して、操作をエミュレートする。
SeleniumやWatir等のブラウザを通したテストだらけにしない
Seleniumなどのテストは、ブラウザをテストケース毎に起動して操作するので大変時間がかかる。ブラウザの起動に2秒くらい掛かったりするし。受け入れテストレベルの自動化は必要で、その際には全レイヤー横断型で画面のエビデンス等が取得できるSeleniumの試験は悪くはないが、全てのテストをレイヤー横断的に実装する必要性はない。経験的にはこのタイプのテストが多いとSlow Testになりやすい。入力チェック等のバリデーションはモデル単体でテストできるだろうし、本当にブラウザを通したテストが必要なテスト項目なのかをよく考えること。
テストの独立性を高める。他のテストに依存させない
テストの実行もユーザーストーリーと一緒でIndependentが望ましい。依存性の高いテストは複数のテストをシーケンシャルに実行することになりテストに時間がかかりやすい。また依存性が高いと仕様変更等があった際に多くのテストが動作しなくなる問題も発生しうる。テストのスコープを明確にすること。
テストを同一マシン上でも並列で動作するようにする
上記に関連してテストを同一マシン上で並列に実行できるようにする。このようにしようとすると必然的にテストにおいてデータベースの依存性を排除したりテストを小さい粒度に保つようになる。I/Oにボトルネックがない場合はテストの並列実行は効果が望める。
テストケースのsetUpメソッドを効率化する
各テストケースでは毎回ケース毎にsetUpメソッドが走ることが一般的だ。すなわちsetUpメソッドが遅いとテストの件数に比例してテストにかかる時間が長くなる。ムダなことをしていないかをチェックすべきだ。また前述の通りバカでかいテストデータを読むこむようなことは必然的な理由がない限り避けるべきだ。
それでは。