私はRSpecでテストをこんな感じで書いてる
私がRSpec使ってテスト書く時はこんな感じで書いてるよ〜ってのを書いてみた。*1
テストを書く順番について
TDDでコードを書く場合、先にテストを書く事になります。
そして、そのテストを書く順番ですが、私は下記のような順番で書くように意識しています。
- 設計する
- describe を書く
- itを書く
- subjectを明確にする
- before(context)を明確にする
その他に、気をつけている点はこんな感じ
- 別のメソッド呼ぶ時は基本的にstubなどで潰す
- contextは「〜の場合」、it は「〜であること」になるようにする
一つずつ、詳細を書きます。
設計する
テストを書き始める前に、まず実装しようとしてるクラス、メソッドを簡単に設計します。
少なくとも、「クラス名」「クラスメソッド or インスタンスメソッド」「メソッド名」「メソッドの戻り値」ぐらいは決めます。
describe を書く
設計したクラス、メソッド名に合わせてテストを書き始めます。
インスタンスメソッドの場合は下記のように "#〜" で書きます。クラスメソッドの場合は".〜"になるようにしてます。
+# -*- coding: utf-8 -*- +require_relative 'user' + +describe User do + describe "#admin?" do + end +end
詳細は後述しますが、これはrspecの実行結果で「それっぽい」出力にするため。
it を書く
まず、「◯◯が管理者であること」のように"結果"から考える。
で、それをspecに書く。
# -*- coding: utf-8 -*- require_relative 'user' describe User do describe "#admin?" do + it { should be_admin } end end
subject を明確にする
次に、「◯◯」の部分を明確にする。
「管理者のユーザ」として、specに書いてみる。
# -*- coding: utf-8 -*- require_relative 'user' describe User do describe "#admin?" do + subject { @admin_user } it { should be_admin } end end
before(context) を明確にする
subject で指定している @admin_user をbefore で用意する。
# -*- coding: utf-8 -*- require_relative 'user' describe User do describe "#admin?" do + before { @admin_user = User.new(role: 'admin') } + subject { @admin_user } it { should be_admin } end end
他のパターンも作成し、context を分ける。
ここで、context の内容が、before と一致するように気をつける。
require_relative 'user' describe User do describe "#admin?" do - before { @admin_user = User.new(role: 'admin') } + context "管理者の場合" do + before { @admin_user = User.new(role: 'admin') } + + subject { @admin_user } + it { should be_admin } + end + + context "一般ユーザの場合" do + before { @user = User.new(role: nil) } + + subject { @user } + it { should_not be_admin } + end - subject { @admin_user } - it { should be_admin } end end
別のメソッド呼ぶ時は基本的にstubなどで潰す
例えば「管理者のリンディさんだけシステムを起動できる」という機能を作る必要があり、テストを書く場合、admin? のテストは済んでいるため、stub!で潰します。
# -*- coding: utf-8 -*- require_relative 'user' describe User do describe "#admin?" do context "管理者の場合" do before { @admin_user = User.new(role: 'admin') } subject { @admin_user } it { should be_admin } end context "一般ユーザの場合" do before { @user = User.new(role: nil) } subject { @user } it { should_not be_admin } end end + + describe "#runnable_system?" do + context "管理者がリンディさんの場合" do + before do + @lindi = User.new(name: 'Lindi') + @lindi.stub!(admin?: true) + end + + subject { @lindi } + it { should be_runnable_system } + end + end end
このようにしておく事で、仮に管理者の判定処理( User#admin? )が「管理者はroleが'admin'、もしくはskillが'SS'」みたいな仕様に変わっても、このテストはfailしなくなります。
contextは「〜の場合」、it は「〜であること」になるようにする
まず始めに、この記事で例として書いていたテストを普通に実行した時の出力を紹介します。
$ rspec user_spec.rb ... Finished in 0.00216 seconds 3 examples, 0 failures
このままでもrspecは実行出来るのですが、オプションで format を指定すると、次のようになります。
- f d は --format documentation と同じです。
$ rspec -f d user_spec.rb User #admin? 管理者の場合 should be admin 一般ユーザの場合 should not be admin #runnable_system? 管理者がリンディさんの場合 should be runnable system Finished in 0.00236 seconds 3 examples, 0 failures
こんな感じで「◯◯は、△△の場合、〜〜であること」の形になるように意識します。
例: User#admin?のメソッド は、管理者 の場合、admin であること
- ◯◯:メソッド名
- △△:状況(context)
- 〜〜:結果
まとめ
「私がどう書いているか?」を書いただけなので、このやり方が正しいとかではないです。*2
ただ、「itから書いて〜」という私のような書き方が少し検索しても見当たらなかったので、何かの参考になるかなーと書いてみました。
以下、リンク集
はじめに注意点を一つ。
ruby周りのwebの情報は情報が古くなっている事が多いです。出来るだけ、英語の公式ドキュメントやソースコードも読む癖をつけた方が良いです。
あと、新しい情報を探す時に「rails capistrano 2012」のように、調べたい内容の最後に西暦を入れると新しい情報が見つけやすいです。普通に検索した後、念のため最近使った人のブログ記事を検索し、目を通しておく事をおすすめします。
写経してみる
t-wada さんの記事がとても参考になる
- RSpec の入門とその一歩先へ - t-wadaの日記 http://d.hatena.ne.jp/t-wada/20100228/p1
ただ、この記事はruby 1.8、rspec 1.3.0の内容なので、その点には注意する必要がある。
下記に気づいた点を記載しておく。
RspecをRailsで使う時の事が分からない
web上の他の資料
rails 3.2.xの情報。
- RSpecでRailsのテストをしてみるテスト。 | Ginpen.com http://ginpen.com/2012/02/14/rspec-rails/
rails2.x の頃の情報なので、一部古いので注意
- Rubyist Magazine - スはスペックのス 【第 1 回】 RSpec の概要と、RSpec on Rails (モデル編) http://jp.rubyist.net/magazine/?0021-Rspec#l50
参考書籍
The RSpec Book (Professional Ruby Series)
- 作者: David Chelimsky,Dave Astels,Zach Dennis,角谷 信太郎,豊田 祐司,株式会社クイープ
- 出版社/メーカー: 翔泳社
- 発売日: 2012/02/22
- メディア: 大型本
- 購入: 7人 クリック: 141回
- この商品を含むブログ (19件) を見る