ドットインストールの学習を元に、はじめてRSpecを動かしてみます。
動作環境
- Ruby 2.3.0
- RSpec 3.4.4
- Cloud9
失敗するクラスを書く
サンプルのテストコードを作成する。
RSpec.describe "A calc" do
# itで囲まれた範囲がexample
# 期待される振る舞いのこと
it "given 2 and 3, returns 5" do
# この時点では存在しないクラス
calc = Calc.new
# 期待値:expectで記述する
expect(calc.add(2, 3)).to eq(5)
end
end
実行結果
Fは失敗(Failure)を表す。 期待される振る舞いが1個あって、そのうち1つが失敗している。
$ rspec
F
Failures:
1) A calc given 2 and 3, returns 5
Failure/Error: calc = Calc.new
NameError:
uninitialized constant Calc
# ./spec/cals_spec.rb:4:in `block (2 levels) in <top (required)>'
Finished in 0.00096 seconds (files took 0.2081 seconds to load)
1 example, 1 failure
Failed examples:
rspec ./spec/cals_spec.rb:2 # A calc given 2 and 3, returns 5
仮実装を行う
上記のテストコードをパスするために仮実装を行う。 仮実装を行う理由は、テストコードの間違いがないかを確認するため。 いきなり実装をしてしまうと、テストコードが間違っている場合、テストコードと実装のどちらに誤りがあるかわからなくなる。
仮実装したクラス
class Calc
def add(a, b)
5 # 仮実装(テストコードの間違いがないかをまず確かめる)
end
end
修正したテストコード
require 'calc'で仮実装したクラスを読み込む。
require 'calc'
RSpec.describe "A calc" do
# itで囲まれた範囲がexample
# 期待される振る舞いのこと
it "given 2 and 3, returns 5" do
# この時点では存在しないクラス
calc = Calc.new
# 期待値:expectで記述する
expect(calc.add(2, 3)).to eq(5)
end
end
実行結果
今度は成功する。 成功した場合は、.(ドット)が表示される。
$ rspec . Finished in 0.00253 seconds (files took 0.11715 seconds to load) 1 example, 0 failures
2サイクル目を回す
テストコードの追加
計算ロジックに対する、2つ目のテストを追加する。 違った角度からテストを加えることを、三角測量と呼ぶらしい。
require 'calc'
RSpec.describe "A calc" do
# itで囲まれた範囲がexample
# 期待される振る舞いのこと
it "given 2 and 3, returns 5" do
# この時点では存在しないクラス
calc = Calc.new
# 期待値:expectで記述する
expect(calc.add(2, 3)).to eq(5)
end
# 三角測量(違った角度からテストを加えること)
it "given 5 and 8, returns 13" do
# この時点では存在しないクラス
calc = Calc.new
# 期待値:expectで記述する
expect(calc.add(5, 8)).to eq(13)
end
end
実行結果
2つめのテストに対する実装は行っていないためエラーとなる。 期待値が13だったのに、5がきたことが原因。
$ rspec
.F
Failures:
1) A calc given 5 and 8, returns 13
Failure/Error: expect(calc.add(5, 8)).to eq(13)
expected: 13
got: 5
(compared using ==)
# ./spec/cals_spec.rb:17:in `block (2 levels) in <top (required)>'
Finished in 0.03919 seconds (files took 0.13237 seconds to load)
2 examples, 1 failure
Failed examples:
rspec ./spec/cals_spec.rb:13 # A calc given 5 and 8, returns 13
処理の実装
仮実装ではなく、実際の処理を実装する。 仮実装に対して、明らかな実装と呼ぶ。
class Calc
def add(a, b)
# 5 # 仮実装(テストコードの間違いがないかをまず確かめる)
a + b # 明らかな実装
end
end
実行結果
2つのテストが成功することを確認。
$ rspec .. Finished in 0.00141 seconds (files took 0.12859 seconds to load) 2 examples, 0 failures
リファクタリング
テストコードや実装の重複部分を取り除く。
テストコード
beforeブロックを使って、処理の共通化を行う。
require 'calc'
RSpec.describe "A calc" do
# 共通化のためのbeforeブロック
# :exampleで、それぞれのexample開始前に実行する
# :contextで、最初の1回だけ実行する
# 省略すると、:exampleになる
before do
# テストコード全体で参照する変数は、@をつける
@calc = Calc.new
end
# itで囲まれた範囲がexample
# 期待される振る舞いのこと
it "given 2 and 3, returns 5" do
# 期待値:expectで記述する
expect(@calc.add(2, 3)).to eq(5)
end
# 三角測量(違った角度からテストを加えること)
it "given 5 and 8, returns 13" do
# 期待値:expectで記述する
expect(@calc.add(5, 8)).to eq(13)
end
end
リファクタリング後の実行結果
2つのテストがパスすることを確認。
$ rspec .. Finished in 0.00145 seconds (files took 0.1221 seconds to load) 2 examples, 0 failures