ドットインストールの学習を元に、はじめて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