rspec
TRANSCRIPT
RSpec
一ヶ月さわさわしたのでまとめてみた
@yuuto
今日やること
Rspec 周りの基本的なところをざーっと。 独学なので間違ってても知りません。
環境構築とかは書いてません。 WEB+DB Press vol.61 あたりが詳しいかも。
環境
Ruby 1.8.7,Rails 3.0.7,Rspec 2.4.0↓GemFile のテスト部分
RSpec とは
プログラムの振る舞いを記述するための DSLTDD ではなく振る舞い駆動開発( Behaviour Driven Development: BDD) のための言語
DSL って?
ドメイン特化言語( DomainSpecificLanguage: DSL) 要はとある目的のために設計された言語の
こと Rspec でいうと、プログラムの振舞を記述
するという目的のために作られた言語、ということ
振舞い
クラスやメソッドの挙動のこと挙動を仕様( spec )と言い換えても OK
テストを作るのと何が違うの?
テスト駆動だと・・・ 仕様を決定→それをもとにテストを作成→
テストが通る実装を行う振舞い駆動だと・・・ 仕様を定義( spec を記述) → Rspec を通
る実装を行う Rspec だと2ステップで分かりやすい
(つってもそこまで違いはないような気もする・・・)
RSpec の書き方は?
例えばこんな感じ
Rspec の書き方は? (2)
describe と context 振舞いをざっくり説明 describe で対象、 context で状況を記述
(どっちも直接何かをしてくれるわけではないよ)
ネスト可能
Rspec の書き方は? (3)
before テスト前に行う処理を記述
subject テスト対象を記述
it テストを記述
実行するとこんな感じ
Describe や it で書いた文言がそのまま出てます。※ この出力が仕様書のようになるのが理想
it と its の違い
it と its の違い (2)
Its は subject で指定した要素の属性を指定できて、2種類の使い方がある シンボルで指定(さっきの。) 文字列で指定
文字列だと↓みたいにネストでの指定もできる
subject {@empty_array} its ('methods.size') { should == 248 }
matcheractual.should matcher(expected) actual.should_not matcher(expected)
should は、 actural を matcher の条件を満たすことを期待するという意味。should と should_not は Object に定義されている。
matcher(2)
演算子マッチャ (>,<,==…)ビルトインのマッチャ( have().items,include(),match()… )be_xxxx(be_empty… メソッドの前に be_ )be_true と be_falsehave_xxx(has_xxx)
{:a => "A"}.has_key?(:a)カスタムマッチャ(自分で定義するマッチャ)
stub
コールに対して定義された結果を返す Model(activerecord) に対してよく使う
・ User#create がコールされたときは User.new を返す。・ User#find_by_name がコールされたときは、 factory_girl で定義されている「 default_user 」を返す。※factory_girl については後ほど。
mock
コールに対して定義された結果を返して且つコールされたことを検証する
spec
実行結果
Webmock
httpリクエストを乗っ取ってレスポンスを指定できる Httpリクエストするのにどんなライブラリ使ってても stub できるので便利
stub_request の括弧内が条件。この条件にマッチするリクエストを行われたら、実際にリクエストする代わりにto_return に記述したレスポンスを返却する。
factory_girl
Test用のモデルデータを生成してくれる${PROJECT_HOME}/spec/factories配下にモデルに対応する rbファイルを作成モデル間の関連を定義できたりする
factory_girl(2)
Factoryファイル
Specファイル
Factory(:~ ) もしくは Factory.create(:~ ) で DB登録。一部だけデータ変えることも可能。インスタンスを作りたいだけなら Factory.build(:~ ) で。
定義したものを継承( parent 指定)してさらに定義とかできる。
database_cleaner
Factory_girl とかで DB登録したデータを自動で消してくれる。@ran_tan曰く、「デフォで消してくれますよ?」とか言ってたけど自分の環境だと消えないので仕方なく導入。spec_helper.rb に削除するタイミングを記述。
Database_cleaner(spec_helper.rb)
:each, :all
before,after のデフォルトは :each:each は it それぞれに対して処理される:all は親ノードに対して一回のみ処理される
:each, :all(2)
routes.rb に定義していれば、 contollerの spec では「 get :index 」みたいにコールできたり、「 controller.hoge 」みたいにテスト対象を controller という変数で参照できるが、これは it内か before(:each) のみ。 before(:all) だと routes の読み込みが終わってないっぽい?
参考文献
WEB+DB PRESS vol.61 特集 2 Rails3 テスト最前線
るびま http://jp.rubyist.net/magazine/?0021-Rspec#l29
t-wada の日記 http://d.hatena.ne.jp/t-wada/20100228/p1
Func09 http://www.func09.com/wordpress/archives/532
おわり。