Test::Unit と RSpec と Shoulda
昨日の記事 続・Rails 3.x 時代のテストフレームワーク では、Rails で使用できるテストフレームワークの基礎知識と相互関係についてまとめました。
今日は、Test::Unit と RSpec と Shoulda を具体的に比較してみたいと思います(Cucumber については、別の機会に…)。
例として「変数 @total に文字列 '100' をセットすると、式 @total.to_i は 100 を返す」というテストケースを考えましょう。
純粋な Test::Unit ではこのように書きます。
require 'test/unit'
class SimpleTest < Test::Unit::TestCase
def test_should_return_100
@total = '100'
assert_equal(100, @total.to_i)
end
end
Rails の ActiveSupport を読み込むと次のように書けるようになります。
require 'rubygems'
require 'test/unit'
require 'active_support'
class SimpleTest < ActiveSupport::TestCase
test "should return 100" do
@total = '100'
assert_equal(100, @total.to_i)
end
end
純粋な Test::Unit の場合は、test_should_return_100 のようにメソッド名の中でテストケースの説明をしなければなりませんが、ActiveSupport による拡張のおかげで "should return 100" のように空白区切りのフレーズとして書けるので、可読性が増しています。
RSpec の場合は、次のように記述します。
require 'rubygems'
require 'rspec'
describe '#to_i' do
it "should return 100" do
@total = '100'
@total.to_i.should == 100
end
end
RSpec では test の代わりに it を使います。その結果、テストケースの説明がより英語の文として自然になります。また、@total.to_i の戻り値が 100 と等しいことを @total.to_i.should == 100 と表現しています。さらに、"it" が何であるかを示すため describe ... end で全体を囲む必要があります。
最後に Shoulda の場合です。
require 'rubygems'
require 'shoulda'
class SimpleTest < Test::Unit::TestCase
context '#to_i' do
should "return 100" do
@total = '100'
assert_equal(100, @total.to_i)
end
end
end
全体としては、Test::Unit の書き方を踏襲しています。@total.to_i が 100 に等しいことは、assert_equal メソッドで調べています。
ActiveSupport が test メソッドを導入したように、Shoulda は should メソッドを導入しています。
context メソッドの役割は、RSpec の describe メソッドのそれと同じです。いま何について調べている(振る舞いを記述している)のかを明示しています。ただし、RSpec と異なり context ... end の記述は必須ではありません。
以上、極めて一面的ではありますが、Test::Unit と RSpec と Shoulda を比較してみました。Shoulda が Test::Unit の拡張であるのに対し、RSpec は Test::Unit とは全く異なる書き方を我々に要求しています。RSpec は古き良き assert_equal メソッドを捨てて @total.to_i.should == 100 という新奇な書き方を導入しました。この点だけで RSpec を評価すべきではありませんが、RSpec の立ち位置を象徴する特徴であることは間違いありません。
RSpec のもたらす変化は有益でしょうか。仮に有益だとしても、それは Test::Unit の伝統を捨てるだけの価値があるでしょうか。
この点で、Rails コミュニティの見解は分かれています。
そもそも @total.to_i.should == 100 などの新しい書き方自体が改悪である、と完全否定する人がいます。あるいは、新しい書き方が合理的であることを認めつつも、既存コードの書き換えや学習のために費やされるコストに見合わないと主張する人がいます。また、JUnit や NUnit に慣れている Java や .NET の開発者が Ruby に挑戦する(乗り換える)時の障害になると心配する人もいます。
しかし、Rails コミュニティには新奇なものでも合理的でさえあれば(コストや障害は度外視して)受け入れる傾向があります。実際、REST 導入や Merb との統合などの相当に大きな変化を経て、Rails の今の姿があります。歴史の短いフレームワークを採用する決断をした人々の持つ、この性向はなかなか変わるものではありません。
私自身は、テストフレームワークの選択についてまだ少し迷っています。プログラマーとしての立場、経営者としての立場、あるいは教育者としての立場からそれぞれ考えると、RSpec の魅力も理解できるし、批判や心配の声も理解できます。プログラマーとしては、RSpec での開発に慣れるにつれ、Test::Unit には戻りたくない気持ちが強くなってきています。Test::Unit + Shoulda の組み合わせでは物足りないと感じています。本稿で挙げた単純な例ではうまく伝わらないかもしれませんが、実際のところ RSpec は書きやすく読みやすいのです。
興味深いことに、アメリカの技術系出版社 The Pragmatic Bookshelf は Rails のテストに関係する 2 つの書籍を 2010 年に相次いで出版しようとしています。
- The RSpec Book: Behaviour Driven Development with RSpec, Cucumber, and Friends
- Rails Test Prescriptions: Keeping Your Application Healthy
前者は文字通り RSpec についての書籍で、後者は RSpec と Shoulda の両方をカバーしています。
Rails におけるテストフレームワークの「標準」がどのような形で落ち着くとしても、今年は TDD/BDD の習慣が急速に広まる年になりそうな予感がしています。
(2010/05/06)
記事に関するご質問は、 hermes@oiax.jp までメールでお送りください。
ウェブサイト構築の発注先を検討されているお客様は、ご相談フォームをご利用ください。
- はじめに
- Rails はエンタープライズの世界で主流になるか (2008/03/29)
- Rails 2.0 ベンチマーク (2008/03/30)
- テスト駆動開発とデバッグコード (2008/04/07)
- Git or Mercurial (2008/04/22)
- RESTful Ruby on Rails -- その美しさと難しさ (2008/04/23)
- RESTful Ruby on Rails -- 単数と複数 (2008/04/24)
- Rails のソースコードを読む (2008/05/02)
- sudo: no passwd entry for app! (Capistrano 2.3.0) (2008/05/12)
- Rails on GlassFish (2008/06/18)
- 「Ruby は型宣言がないけど、ちゃんとしたシステムに使えるのか」という質問にどう答えるか (2008/11/23)
- 「Ruby はスクリプト言語だけど、遅くないですか」という質問にどう答えるか (2008/11/24)
- どのプログラミング言語が将来的に有望か (2009/01/10)
- どのフレームワークが将来的に有望か (2009/01/11)
- フレームワーク対 CMS (2009/01/12)
- Rails 2.3 で spawner/reaper は DEPRECATED に (2009/03/25)
- db/seeds.rb (2009/06/08)
- LESSとSass (2009/08/03)
- Rails 2.3.4 と I18n (2009/08/15)
- RubyGems のアップデート(上書きインストール) (2010/02/03)
- クリエイティブ・コモンズの Rails 教材 (2010/03/08)
- Yet Another Ruby Reference (2010/03/12)
- Rails で MongoDB を使ってみた (2010/03/23)
- Rails で MongoDB を使ってみた(2) (2010/03/25)
- 祝 Ruby on Rails 3.0 beta2 リリース (2010/04/02)
- Rails 3.x 時代のテストフレームワーク (2010/04/24)
- 続・Rails 3.x 時代のテストフレームワーク (2010/05/06)
- Test::Unit と RSpec と Shoulda (2010/05/06)
- Windows + Rails + MySQL 5.1 (2010/07/20)
- Ruby on Rails 2.3.9 リリース (2010/09/05)
- Railtie と Engine と Plugin の関係 (2010/10/23)
- Rails 3.0 と Internet Explorer (2010/11/19)
- acts_as_list: gem か plugin か (2010/11/29)
- さようならNetBeans/こんにちはRedcar (2011/01/28)
- RubyGems 1.5 が出たけど (2011/02/04)
- はじめる!Rails3 第2巻の執筆を始めました (2011/03/20)
- NetBeans 7.0にRuby on Railsプラグインをインストールする手順 (2011/03/21)
- Resqueを利用したRailsでの非同期処理/バッチ処理 (2011/03/23)
- Resqueワーカーをデーモンとして動かす (2011/04/02)
- はじめる!Rails3 第2巻の執筆(経過報告) (2011/04/23)
- はじめる!Rails3 第2巻の執筆(経過報告 No.2) (2011/05/11)
- Rails 3.1: assign_attributesメソッド (2011/05/14)
- Rails 3.1: has_secure_passwordメソッド (2011/05/27)
- はじめる!Rails3 第2巻の執筆(経過報告 No.3) (2011/06/06)
- Ruby on Rails 3.1 を Windows にインストールする手順をかなり丁寧に説明してみました (2011/07/22)
- Ruby on Rails 3.1 を Mac OS X にインストールする手順をかなり丁寧に説明してみました (2011/08/07)
- はじめる!Rails3 第2巻の執筆(経過報告 No.4) (2011/08/15)
- WindowsマシンにUbuntuをインストールしてRails開発を始めるには (2011/08/29)
- Rails 3.xでISO-2022-JP(JISコード)の電子メールを送る: mail-iso-2022-jp (2011/12/05)
- はじめる!Rails3 第3巻について (2011/12/30)
- NetBeans 7.1にRuby on Railsプラグインをインストールする手順 (2012/01/26)

