LoginSignup
56
59

More than 5 years have passed since last update.

RubyのTDDのベストプラクティス

Last updated at Posted at 2012-07-02

この記事は、RubyのAdvent Calendarの2日目の記事です。
オライリーの『Rubyベストプラクティス』のテスト駆動開発の章をまとめました。
開発環境とrubyとテストに関する記述が入り交じっています。

テストができるように設計する

1.大きなテストにすると、失敗した場合に、どこが原因で引っかかったかわかりにくい
2.小さなテストを追加する→レッドになるようにする→グリーンにする→リファクタリングする→始めに戻る
3.単純なテストから追加する
4.可読性向上のため、mustメソッドを使う

must.rb
class TC_Foo < Test::Unit::TestCase
  def setup
    @obj = Foo.new
  end

  must "be foo" do
    assert_equal("foo", @obj.foo)
  end
  must "be bar" do
    assert_equal("bar", @obj.bar)
  end
end

mustメソッドの実装は下記の通り。
https://github.com/sandal/rbp/blob/master/testing/test_unit_extensions.rb

テスティングの基礎

1.上記と重なるが、レポートが詳細な意味を持つようにするために、テストケースは小さくアトミックに保つ
2.例外をテストする

例外が起きることを期待する場合
class LockBoxTest < Test::Unit::TestCase
  def setup
    @lock_box = LockBox.new( password:"secret",
                 content:"My secret message") 
  end

  must "raise an error when an invalid password is used" do
    assert_raises(LockBox::InvalidPassword) do
      @lock_box.unlock("kitten")
    end
  end
  must "Not raise error when a valid password is used" do
    assert_nothing_raised do
      @lock_box.unlock("secret")
    end
  end
end

3.rakeタスクを使ってテストを自動実行する

rake.rb
require 'rake/testtask'

task :default => [:test] 

Rake::TestTask.new do |test|
  test.libs << "test"
  test.test_files = Dir["test/test_*.rb"]
  test.verbose = true
end```
##高度なテストテクニック
1.外部とのインタラクションと内部処理を切り分ける
2.外部のテストには、モックとスタブを使う。おすすめはflexmockライブラリ

```ruby:
require 'flexmock/test_unit'

class HapinessTest < Test::Unit::TestCase
  def setup
    @questioner = Questioner.new
  end

  must "respond 'Good I'm Glad' when inquire_about_hapiness gets 'yes'" do
    stubbed = flexmock(@questioner,:ask => true)
    assert_equal "Good I'm Glad",stubbed.inquire_about_hapiness
  end

  must "respond 'That's Too Bad' when inquire_about_hapiness gets 'no'" do
    stubbed = flexmock(@questioner,:ask => false)
    assert_equal "That's Too Bad",stubbed.inquire_about_hapiness
  end
end

3.xmlの比較は、一つにまとめてするのではなく、nokogiriライブラリを使って分解してやろう

整理しておく

1.ライブラリファイルにテストを組み込む

if文でラップするだけ
class Foo
  #...
end  

if __FILE__ == $PROGRAM_NAME
  require "test/unit"

  class TestFoo < Test::Unit::TestCase
    #test
  end  
end

2.テストヘルパーを一つのファイルにまとめて定義して、pathで直接requireする
3.組み込みのアサートで間に合わないなら、カスタムアサーションをassert_blockでつくる

assert_block
def assert_in_zone(expected,person)
  assert_block("Expected #{person.inspect} to be in Zone #{expected}") do
    person.current_zone.eql?(Zone.new(expected))
  end
  assert_block("Expected #{person.inspect} not to be in Zone #{expected}") do
    !person.current_zone.eql?(Zone.new(expected))
  end
end```##後口上ruby特有のベストプラクティスというよりは、テスト一般のお話でした。
以前にRailsの2系を少し触った程度で、普段Rubyを使わないのですが、各方面からRails3系を推されたため、最近オライリーの『Rubyベストプラクティス』を現在読んでいるところです。何か良いtipsや本があればご紹介お願いします。
56
59
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
56
59