describe Order do
before do
order.add_entry(LineItem.new(:item => Item.new(
:price => Money.new(1.11, :USD)
)))
end
let(order) { Order.new }
it "sums the prices of its line items" do
order.add_entry(LineItem.new(:item => Item.new(
:price => Money.new(2.22, :USD),
:quantity => 2
)))
expect(order.total).to eq(Money.new(5.55, :USD))
end
end
Rspecはrspec-core, rspec-expectations, rspec-mocksの3つにわかれており、それぞれRspecの基本文型、多様な比較演算、モックオブジェクトを定義している。このドキュメントは、文法に焦点を当てるため、rspec-coreの中の基礎的な部分と、Rails用にrspec-rails, capybaraが拡張する文法について触れる。
テストの中身の書き方については、http://qiita.com/awakia/items/d880250adc8cdbe7a32f を参照
基本文型
https://github.com/rspec/rspec-core
https://www.relishapp.com/rspec/rspec-core/v/3-0/docs/example-groups/basic-structure-describe-it
describe <クラス名> do
it "<期待する動作の内容>"
# ...
end
context "<条件の内容>" do
it "<contextの条件下で期待する動作の内容>" do
# ...
end
end
end
ここで、
-
context
は、describe
に置き換え可能 -
it
は、specify
またはexample
に置き換え可能
なので、文脈に合わせて使いやすい用語を使えば良い。
なお、デフォルトの設定では、名前として<クラス名>_spec.rb
というようにサフィックスとして_spec.rb
がないとrspec
コマンドで全体を走らせた時に無視されるようになるので気をつけること。
何をしているか
-
describe
,context
はExampleGroupを生成 -
it
,specify
,example
はExampleを生成
なお、topレベルのdescribe
はExampleGroupを生成するが、役割はそれだけではない。
Railsを使っている場合
rspec-railsというのを使う。
これは、expect ... to
の後に使える
- be_a_new
- render_template
- redirect_to
- route_to
- be_routable
などのRails用のMatcherを提供する他、
- Model
- Controller
- View
- Request
- Feature
- Mailer
- Routing
- Helper
など、それぞれのタイプの特徴に合わせたスペックの書き方を提供する。
例えばモデルタイプのテストだとspec/models
の下におくか
describe ... type: :model
としてテストを書く。
それぞれのタイプにより何がロードされるかや、使えるメソッドなどが異なり、ここに書ききれないので、それぞれのテストを書く際にドキュメントを参照すると良い。
ドキュメントは以下だが、概要はgithubの方がわかりやすいので詳しく知りたくなった時のみこちらを参照すると良い。
https://www.relishapp.com/rspec/rspec-rails/v/3-0/docs/directory-structure
Capybaraを使っている場合
rspec-railsのfeatureテストはほぼcapybaraの使用を前提としている。
Capybaraはユーザーがブラウズする課程をテストでそのまま書くようなFeatureテストを作成するときに便利なgem
https://github.com/jnicklas/capybara#using-capybara-with-rspec
これを使っている場合、
-
describe ... type: :feature
の代わりにfeature
-
before
の代わりに、background
-
it
の代わりに、scenario
-
let
の代わりにgiven
が使えるようになり、より自然な英語で以下のように書けるようになる。
feature "Signing in" do
background do
User.make(:email => 'user@example.com', :password => 'caplin')
end
given(:other_user) { User.make(:email => 'other@example.com', :password => 'rous') }
scenario "Signing in as another user" do
visit '/sessions/new'
within("#session") do
fill_in 'Login', :with => other_user.email
fill_in 'Password', :with => other_user.password
end
click_link 'Sign in'
expect(page).to have_content 'Invalid email or password'
end
end