1人で考えてたら行き着いたRspecの書き方とか その1

rspec-core (2.13.1)
ruby2.0

Rspecってすごく個性でると思うので複数人で開発する時は規約を設けないとだめかも。

letメソッド使う

let(:word) { FactoryGirl.create(:word) }

メモ化っていうらしい。
letの引数に書いているシンボル名を試験内で呼ぶとローカル変数のように使える。
同一試験内なら同じ値を返すみたい。
インスタンス変数使うとスコープがわかりにくなる(?)ので変に疲れる心配ないです。
http://kmrshntr.hatenablog.jp/entry/20101124/1290607173

itに引数は渡さない

よっぽどロジックに依存する試験の場合は itに試験内容を書くけど、基本的にマッチャーが自動で出力する文字に頼る。
(ただし試験対象をdescribeで明示してあげないとrspecを流した時にわかりにくくなる。)
こうすることで試験内容を文字で書かなくていいのでさくさく書ける。

describe Word do
  describe "#hoge" do     # 対象を明示する
    it { should be_nil }      # => - should be nil
  end
end

subject使う

レシーバを省略できる。

describe "管理画面" do
  before { login_user(admin(role: 'admin')) }
  describe "サイドメニュー" do
    before { render "layouts/admin/submenu" }
    subject { rendered }
    it { should match /ダッシュボード/ }
    it { should match /画像一覧/ }
    it { should match /カテゴリ一覧/ }
    it { should match /記事/ }
    it { should match /記事一覧/ }
  end
end

request specは極力書かない

request specはとにかく遅い。
visitして have_contentで落ちてないかの試験は書くべきだと思うけど、
visitしてステータスコードの確認してたらcontroller specへ。
h1に表示されている文字の試験など単純なものははview specへ。
capybaraを入れたらspecを書くのがすごく楽になるけどspec増えてきたら時間かかってしまう。

springを使って高速spec

起動が早くなります。

$ gem i spring
$ spring rake spec

二回目の起動から爆速になります。

レイヤー毎で試験をする

けっこう使ってます。

rake spec:controllers
rake spec:requests
rake spec:models
rake spec:views

よく使う記述をモジュールに切出して呼び出す

APP_ROOT/spec/support/login_helper.rb を作成する。

module LoginHelper
  def admin_login(role: "admin")
    admin = find_admin_user_or_create(role: role)
    visit admin_login_path
    fill_in 'username', with: admin.username
    fill_in 'password', with: "password1"
    click_button 'サインイン'
  end

  def find_admin_user_or_create(role: 'admin')
    role = Role.find_by!(name: role)
    if admin = Admin.where(role: role).first
      admin
    else
      FactoryGirl.create(:admin, role: role)
    end
  end
end

spec_hepler.rbで読み込む。

RSpec.configure do |config|
  ....
  config.include LoginHelper , :type => :controller # typeオプションが指定しない場合すべてのspecで呼べる
  ...
end

後はmoduleに書いてるメソッドを試験で呼ぶだけでよい。