ayuminのあまり更新しないBlog

筆不精なのでめったに更新しません

独習 スはSpecのス

角谷さんが関西Ruby会議で講演した「スはSpecのス」の実演をトレースしてTDDとRSpec、Autotestの使い方を学びました。

スライドはこちら
http://www.slideshare.net/kakutani/s-is-for-spec-at-rubykansai25

動画はこちらからみることができます
http://www.nicovideo.jp/watch/sm3003102


で成果物はこちら
lib/game.rb

class Game
  FrameNumber = 10
  def initialize
    @frame =[]
  end
  def roll pins
    @frame << pins
  end
  def score
    @idx = total = 0
    FrameNumber.times do
      total += score_of_this_frame + bonus
      @idx  += (strike?) ? 1 : 2
    end
    total
  end
  private
  def score_of_this_roll  ; @frame[@idx]                          end
  def score_of_this_frame ; score_of_this_roll + @frame[@idx + 1] end
  def strike? ; score_of_this_roll  == 10                         end
  def spair?  ; score_of_this_frame == 10                         end
  def bonus   ; (strike? or spair?) ? @frame[@idx + 2] : 0        end
end

spec/bowling_spec.rb

$: << File.dirname(__FILE__) + '/../lib'
require 'rubygems'
require 'spec'
require 'game'
describe Game do
  before do
    @game = Game.new
  end
  describe "全部ガターの場合" do
    before do
      20.times{ gutter! }
    end
    it "点数は0点になること" do
      @game.score.should == 0
    end
  end
  describe "全部1本倒した場合" do
    before do
      20.times{ @game.roll 1 }
    end
    it "点数は20点になること" do
      @game.score.should == 20
    end
  end
  describe "ストライクの場合" do
    before do
      strike!
      @game.roll(5);@game.roll(3)
      16.times{ gutter! }
    end
    it "点数は26点になること" do
      @game.score.should == 26
    end
  end
  describe "全部ストライクの場合" do
    before do
      12.times{ strike! }
    end
    it "点数は300点になること" do
      @game.score.should == 300
    end
  end
  describe "スペアの場合" do
    before do
      spair!
      @game.roll(5);@game.roll(2)
      16.times{ gutter! }
      # |7 3|5 2|
      #   15| 22|
    end
    it "点数は22点になること" do
      @game.score.should == 22
    end
  end
  describe "受入れテストケースの場合" do
    before do
      [1,4,4,5,6,4,5,5,10,0,1,7,3,6,4,10,2,8,6].each do |pins|
        @game.roll(pins)
      end
    end
    it "点数は133点になること" do
      @game.score.should == 133
    end
  end
  private
  def gutter!; @game.roll(0)                end
  def strike!; @game.roll(10)               end
  def spair!;  @game.roll(7); @game.roll(3) end
end

やってる途中で気がついたんですが、Autotestではテスト対象コード(game.rb)の方はいちどテストに失敗していないと内容を更新してもテストされないみたい。テストコード(bowling_spec.rb)の方はいつ更新してもテストが実行されました。