RSpecを使ったテストコードを読もう:Railsコードリーディング〜scaffoldのその先へ〜(2)(3/4 ページ)
優れたプログラマはコードを書くのと同じくらい、コードを読みこなせなくてはならない。優れたコードを読むことで、自身のスキルも上達するのだ(編集部)
モデルのスペックを読んでみよう
では、SKIPのグループ機能のモデル部分を使って、スペックのコードリーディングをしていきましょう。
今回、イメージをつかむためにも、シンプルなメソッドを選びます。Groupモデルのhas_waitingというメソッドです。ファイルの場所はapp/models/group.rbになります。このメソッドは、前述の承認制の仕様で、グループに対して「参加承認待ち」のユーザーがいるかどうかを判定するために使われます。
77 def has_waiting 78 if group_participations.find(:all, :conditions =>["waiting = ?", true]).size > 0 79 return true 80 end 81 return false 82 end
非常に簡単ですね。グループ参加状況(group_participation)に、承認待ち(waiting)でデータがあれば、承認待ちのユーザーがいる、というわけです(1行でも書けますが、今回はあえて分岐で表現しています)。
このメソッドの主なロジックは、78行目のif文です。その結果でメソッドは、trueかfalseを返しています。よって、スペックで確かめたいのは、このif文の条件に応じてメソッドの戻り値が期待どおりに変化することです。
では、対応するスペックを見てみましょう。ファイルは、spec/models/group_spec.rbになります。Groupモデルなので、対応するスペックは、_specを付けたファイル名になっています。
59 describe Group, "承認待ちのユーザーがいるとき" do #条件の説明 60 before(:each) do #条件の状態を作り出す 61 @group = Group.new 62 @group_participations = [GroupParticipation.new({ :waiting => true })] 63 @group.should_receive(:group_participations).and_return(stub('group_particip 64 ations', :find => @group_participations)) 65 end 66 it "has_waitingはtrueを返す" do #実施するテストの結果の説明 67 @group.has_waiting.should be_true #実際に検証している文 68 end 69 end 70 71 describe Group, "承認待ちのユーザーがいないとき" do 72 before(:each) do 73 @group = Group.new 74 @group_participations = [] 75 @group.should_receive(:group_participations).and_return(stub('group_participations', :find => @group_participations)) 76 end 77 78 it "has_waitingはfalseを返す" do 89 @group.has_waiting.should be_false 80 end 81 end
59行目のdescribeの後の文字列で、これから実施するテストの条件を説明しています。この場合「承認待ちのユーザーがいるとき」という、先ほどのif文が分岐する条件を表しています。
60〜64行目のbeforeのブロックの中で、「承認待ちのユーザーがいるとき」という条件になるようにメソッドが動作する状態を作り出しています。
そして、66行目のitの後の文字列で実際に動作すべき結果である「has_waitingはtrueを返す」と記述します。実際にメソッドを動作させて戻り値が正しいかを確認しているのは、itのブロックの中の67行目のshouldというメソッドです。
71行目から81行目も同様に、テストする条件と結果が変わっていますが、同様の流れになっています。
スペックでは、基本的にはこのような流れで記述されています。検証すべきロジックが増えるとテストする条件が増えdescribe文の中にもう一段describe文が入るなど複雑性を増しますが、この基本さえ分かっていれば、多少複雑になったとしても、スペックに書かれている内容が理解できるはずです。
さて、ここであらためてdescribeとitのみに注目して、もう一度スペックを見てください。
59 describe Group, "承認待ちのユーザーがいるとき" do 66 it "has_waitingはtrueを返す" do 71 describe Group, "承認待ちのユーザーがいないとき" do 78 it "has_waitingはfalseを返す" do
Groupモデルのメソッドであるhas_waitingの振る舞いが端的に書かれているということに気付けたと思います。このdescribeとitのみの行を切り出してみると、まるでクラスの仕様書のように読めますね。RSpecでは、この内容と同等の結果を出力する機能も用意されています。-cfsオプションを付けて実行すると、以下のように出力されます。
ソースコードリーディングを行っていて、挙動が分からないメソッドがあれば、上記の出力を利用してメソッドの仕様を理解するのも一つの手です。
Copyright © ITmedia, Inc. All Rights Reserved.