まさ@ブログ書き込み中

自由に生きるための英語、プログラミング、考えごとについて色々書いています。

【Rails・RSpec】テストコードの種類についてまとめます

f:id:masaincebu:20180829072220p:plain

Railsチュートリアルでテストコードを書くことを知ったけど、テストコードを書く意義やテストコードの種類、それぞれの特徴を知っておきたいな。

 

そんな人に役立つような情報をこの記事では書いていきたいと思います。

 

僕はいまWebエンジニアとして働いていて、会社では新しくコードを書いたらテストコードも絶対に書くことが必須になっています。

 

そんな中で学んだテストについてまとめたので、ぜひご覧ください。

 

もくじ

  • テストを書く理由は「チームが」アプリケーションの動作に自信を持つため

  • テストには大きく分けてユニットテスト・統合テスト・UIテストがある

  • 書く優先順位はユニットテスト→統合テスト→UIテストの順

 

テストを書く理由は「チームが」アプリケーションの動作に確信を持つため

テストを書く理由について僕の考えをはっきりさせておくと、テストはチームがアプリケーションの動作に確信を持つためにあると考えています。

 

この言葉の主語が「チーム」になっているのが重要です。自分で書いたコードだから絶対に大丈夫だと思っていても、チームの他の人にとっては「本当に大丈夫なの?」と不安になるかもしれません。それを払拭するためにテストを書いて保証をするわけです。

 

実は「テストを書く必要があるのか」というのは宗教論争のようにずっと前から議論されています。

 

例えば「プロダクションコード(アプリケーションのコード)も書くのにテストのためだけにコードを書くことはコストパフォーマンスが悪い」とか「テストはどのみち完璧ではない」という人も居れば「テストを書くことによってプロダクションコードが改善される」という人もいます。

 

色んな意見がありますが、僕は自分のコードを改善する上で、またチームで開発をする上でテストの存在は必要だと思っています。

 

テストには大きく分けてユニットテスト・統合テスト・UIテストがある

テストには、大きく分けてユニットテスト・統合テスト・UIテストの3つがあります。それぞれについて簡単に見ていきます。

 

ユニットテスト

ユニットテストとは、アプリケーションのそれぞれのロジックが正しく動くかどうかをテストするものです。Railsで言えばモデルやコントローラーのテストになります。

 

ユニットテストは正確性、スピード、カバレッジにおいて頼りになります。高速でテストを実行でき、失敗した時にはどこがうまくいかなかったかを厳密に教えてくれます。

 

ユニットテストは一番基本的なテストであり欠かすことができないものですが、それぞれのロジックをテストしているので、ロジックの組み合わせ(結合部分)の確認については弱い(ちゃんとテストできていないことがある)ことが欠点です。

 

RSpecというテストフレームワークの簡単な例をここに載せておきます。

ここではEventモデルのインスタンスが正しい値で作られた時と間違った値の時にちゃんと期待した動作が起こるかをチェックしています。

 

具体的なコードの意味は理解しなくてもかまいません。雰囲気を掴んでいただければ十分です。

 

統合テスト

統合テストとは、先ほどユニットテストの弱点として挙げた結合部分をテストするものです。 フィーチャースペックと呼ぶこともあります。

 

ロジックの組み合わせがちゃんと動作していることを確認できるので、サービスがちゃんと動いていることをテストする1つの方法となっています。

 

統合テストのコードについてはこちらの記事が詳しいです。

Railsチュートリアルの7章の内容が思ってたより深い【テスト編】 - まさ@ブログ書き込み中

 

しかし、このテストに失敗した時に問題となるのは「うまくいかない」ということがわかっても、何が問題なのかはわかりづらいということです。

 

ユニットテストはそれぞれのロジックの細部についてテストをしているので失敗したらわかりやすいのですが、統合テストはそういうわけにはいきません。

 

UIテスト

UIテストとは、サービスを実際に動かして実行するテストのことです。

 

原始的に行うUIテストと言えば実際にアプリケーションをいじってみることでしょうが、それだと何をテストしているのかが人によって異なる上に大変です。そこで、UIテストではプログラムを使って仮想的に文字を入力させたりボタンを押させたりします。

 

UIテストではUI部分からサービス全体がちゃんと繋がっていることをテストするのでとても魅力的ですが、このテストは実行スピードと壊れやすさに問題があります。

 

壊れやすさについて一例をあげると、UIテストで「idが"email"というinputタグに"masa@mail.com"という文字列を入れる」というような動作を書いていた場合、idが変わったりすればすぐにテストは落ちます。もしかしたらemailを入力する必要がなくなるかもしれません。

 

UI部分はサービス本来のロジックよりも頻繁に変更が起きうるものなので、それに合わせたテストも壊れやすいのです。

 

書く優先順位はユニットテスト→統合テスト→UIテストの順

さて、ここまでユニットテストと統合テスト、UIテストの概要について見てきました。読んでくださった皆さんならわかると思いますがどれも一長一短があります。

 

そのため、理想的なテストはそれぞれのテストを組み合わせることです。しかし、実際の開発には時間が限られているので、全種類のテストを完璧に書くことは難しいです。そのため優先順位をつけてテストを書く必要があります。

 

その実行スピードの速さや正確性から考えて、まずはユニットテストを書くことを最優先にすべきだと思います。次に書けるのであれば繋がりをチェックするための統合テスト、最後にどうしても必要であればUIテストを書くといった感じでしょうか。

 

ここらへんは開発現場や対象とするサービスによっても変わるところなので、この考え方は参考程度にしておいてください。

 

今回はテストコードについてまとめました。この情報が皆さんの役に立てば幸いです。