この記事は、RubyのAdvent Calendarの2日目の記事です。
オライリーの『Rubyベストプラクティス』のテスト駆動開発の章をまとめました。
開発環境とrubyとテストに関する記述が入り交じっています。
##テストができるように設計する
1.大きなテストにすると、失敗した場合に、どこが原因で引っかかったかわかりにくい
2.小さなテストを追加する→レッドになるようにする→グリーンにする→リファクタリングする→始めに戻る
3.単純なテストから追加する
4.可読性向上のため、mustメソッドを使う
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タスクを使ってテストを自動実行する
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.ライブラリファイルにテストを組み込む
class Foo
#...
end
if __FILE__ == $PROGRAM_NAME
require "test/unit"
class TestFoo < Test::Unit::TestCase
#test
end
end
2.テストヘルパーを一つのファイルにまとめて定義して、pathで直接requireする
3.組み込みのアサートで間に合わないなら、カスタムアサーションを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や本があればご紹介お願いします。