RSpecのまとめ
概要
BDDを行うためのテストフレームワーク。
準備
gemのインストール。
$ gem install rspec
初期化
$ rspec -init
これを実行すると spec というディレクトリが直下に出来て、その中に spec_helper.rb ファイルが出来る。rspecのテストファイルを作成する際は必ずこれを require する必要がある。
チュートリアル
(1) テスト対象を決める
今回は、/lib/dog.rb を対象とする。
(2) 失敗するテストを書く
下記のテストファイルを作る。
spec/lib/dog_spec.rb
require "spec_helper" require "dog" describe Dog do it "is named 'Pochi'" do dog = Dog.new expect(dog.name).to eq 'Pochi' end end
またテスト対象である Dog クラスもファイルだけ作成しておく。
(でないとテスト実行時にエラーがとなってしまうので)
テストを実行してみます。実行結果は・・
$ rspec spec/lib/dog_spec.rb F Failures: 1) Dog is named 'Pochi' Failure/Error: expect(dog.name).to eq 'Pochi' NoMethodError: undefined method `name' for #<Dog:0x007fcc4f97a8d8> # ./spec/lib/dog_spec.rb:7:in `block (2 levels) in <top (required)>' Finished in 0.00061 seconds (files took 0.55266 seconds to load) 1 example, 1 failure Failed examples: rspec ./spec/lib/dog_spec.rb:5 # Dog is named 'Pochi'
当然、dogの中身がないので失敗します。
テストが成功するように、dog.rbを修正します。
class Dog attr_accessor :name def initialize(name="Pochi") @name = name end end
再度テストを実行してみる。
$ rspec spec/lib/dog_spec.rb . Finished in 0.0074 seconds (files took 0.53777 seconds to load) 1 example, 0 failures
今度は無事成功したのでOK! このテスト作成→失敗→修正→成功までの一連のサイクルがBDD(Behavior Driven Development)の基本的な流れになる。
その他のテスト例
describe User do describe '#greet' do before do @params = { name: 'たろう' } end context '12歳以下の場合' do before do @params.merge!(age: 12) end it 'ひらがなで答えること' do user = User.new(@params) expect(user.greet).to eq 'ぼくはたろうだよ。' end end context '13歳以上の場合' do before do @params.merge!(age: 13) end it '漢字で答えること' do user = User.new(@params) expect(user.greet).to eq '僕はたろうです。' end end end end
describe '#greet' doは、Userクラスのgreetメソッドをテストするということ。
また、beforeは、テスト実行前に必要な共通処理を記載する。
contextは、直訳すると「文脈」や「状況」という意味。つまり、なにかしら条件が異なる場合はcontextを使ってテストを分割する。
インスタンス変数の代わりにletを使う
インスタンス変数の代わりに以下のようにletを使うこともできる。
require 'spec_helper' require 'user' describe User do describe '#greet' do let(:params) {{name: 'たろう'}} context '12歳以下の場合' do before do params.merge!(age: 12) end it 'ひらがなで答えること' do user = User.new(params) expect(user.greet).to eq 'ぼくはたろうだよ。' end end context '13以上の場合' do before do params.merge!(age: 13) end it '漢字で答えること' do user = User.new(params) expect(user.greet).to eq '僕はたろうです。' end end end end
let(:params) {{name: 'たろう'}}がそう。{}が二重になってちょっとわかりにくいが、外側がRubyのブロックの{}で、内側がハッシュの{}だ。
let は遅延評価されるので、それが使われる時に初めて初期化される。つまり、上のテストコードを以下のように書き直すことが出来てしまう。
require 'spec_helper' require 'user' describe User do describe '#greet' do let(:user) { User.new(params) } let(:params) {{name: 'たろう', age: age}} context '12歳以下の場合' do let(:age) {12} it 'ひらがなで答えること' do expect(user.greet).to eq 'ぼくはたろうだよ。' end end context '13以上の場合' do let(:age) {13} it '漢字で答えること' do expect(user.greet).to eq '僕はたろうです。' end end end end
age は params ハッシュの定義時に使われているが、各context内ではじめて実際の値が代入されている。