2012年3月5日月曜日

[rails3]「Unitテスト」と「rspec」 根本的な違いとは

Unitテストとrspecの違いについて見解を述べたい。
そこには部分的ではあるが、明確な思考過程の違いがあると私は思う。

その思考過程の相違により、アプリケーションの規模が大きくなるにつれ、
潜在的なリスクを埋め込む可能性が大きくなる。

だから私はrspecを選らんだ。



  • 思考過程の違いとは

Unitテストの場合
検証したいことを優先的に考え、その後、その検証方法に従えばそのオブジェクトの動作結果がどうなるかということ(オブジェクトの動作)を最後に結論として宣言するプロセス。

rspecの場合は、
オブジェクトの動作・状態変化を優先的に考え、その後、その動作がどうなることが正しいのか(検証項目)を最後に結論として宣言するプロセス。


つまり、動作を先に考えるのか、検証項目を先に考えるのかという相違がある。



上記は絶対的ではなく、あくまでその傾向があると言いたい。


David Chelimsky著のThe RSpec Bookの書籍が非常に理解を助けてくれたので紹介しておく




上記の主張を以下で説明したい。

★ Unitテスト

class BlogTest < ActiveSupport::TestCase
  test "blog_validate" do  
    assert_equal blog.errors.size, 2, 'Failed to validate count'
    assert blog.errors[:user_id].any?, 'Failed to :user_id validate'
 end
end

★ rspec

describe BlogsController do
  describe "#index" do
    context "when logined_user" do
        subject { response }
          it { should render_template("layouts/#{@crtl_head}") }
        end
    end
  end
end



(まだ、rails・rspecについては触りはじめのため、書き方について至らぬ点はご容赦いただきたい。)

上記の赤文字(特に)の記述が「思考過程の違い」の顕著な例を表していると思う。
その次の違いが青文字部分だ。 青文字 部分は代替手段が適応可能なので、少しの違いと表現しておく。


ではテストコードを書くときどのような思考の過程を経るのか順を追ってみよう。


----------------------------------------------------------------------

①(主題)何についてテストするのかを考える

:これは両者共通の書き始めである。Unitテストは class BlogTest の箇所。rspecはdescribe Blog・・・の部分。そもそもテストするにはテストしたい対象を考えなくてはいけないから当然である。

----------------------------------------------------------------------

※ 極論ここから分岐する
②Unitテストの場合
その主題について、何をテストしたいかを考える。
上記記述のtest "blog_validate" の部分だ。(ex : 私はBlogユニットのvalidateがうまくいくかを検証しよう)
Unitテストの場合、対象を定めた後すぐにどんな検証をしたいか(検証内容)を考えるはめになってしまう。
(ただし、このコードが極端なだけなので、書き方次第ではrspecと同等の思考過程を経ることは可能)

<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>

②rspecの場合
その主題について、どんな振る舞いをするのかを考える、また、どんなコンテキストが考えられるのかを考える。

  describe "#index" do
    context "when logined_user" do
この部分である。(ex : blog_controllerの振る舞いはindexアクションがあり、loginしてるかどうかで振る舞いが変わるね)
rspecの場合は、まだ検証内容を検討しない。そのオブジェクトの振る舞いや状態変化を考えなくてはならい。

----------------------------------------------------------------------

(ここが決定的である。)
③Unitテストの場合
上記考えた検証内容にもとづき、オブジェクトの動作・状態変化を考える。
 assert_equal blog.errors.size, 2
   assert blog.errors[:user_id].any?

記述順としては、assert_equal 一致すると断言しよう (検証内容)、blog.errors.size, 2
ブログのエラー数が2つになることを(オブジェクト動作)、という順となる。

ほかにもUnitテストには

assert_generates XX (生み出すことを断言しよう、XXとなることを)
assert_recognizes XX (認識すると断言しよう、XXとなることを)

というような、検証内容を優先して考え、そのおしりにオブジェクトの動作をひもづける傾向があると私は思う。


<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>


③rspecの場合
上記考えたアクションとコンテキストにもとづき、最終的なオブジェクトアクション(subject { response })を考え、そのアクションがどうなるのかを最後に示す。(render_template("layouts/#{@crtl_head}")
つまり、オブジェクトの動作を隅々にとらえたのちに、最後に検証内容(ex : レンダーすること)を紐づけていく。(検証というよりは動作に重きを置く)


以上。


この最後③(特に緑文字の箇所=検証したいオブジェクトの最終的なアクション・状態の位置)がどうにもならない違いである。

プログラムしていく上で、最後にそれを記述するからには自然に最後にそれを考える思考となってしまう。


検証内容だけを頭から考えたところで、そもそもオブジェクトの振る舞い・状態変化を捉えなければ適切な検証を洗い出すことはできないと私は考え、rspecを選んだ。


おそらく青文字の箇所は、書き方次第でどうにかなる。

(しかし、主題やサブ主題、コンテキストを明確にテストコードに埋め込めるrspec がより有利のではないだろうか。Unitテストは3時間ほどしか触っていないので、誤認であれば申し訳ない)



上記はテストツールの触りはじめの所感である。







0 件のコメント:

コメントを投稿