Help us understand the problem. What is going on with this article?

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

More than 5 years have passed since last update.

この記事は、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や本があればご紹介お願いします。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away