まりぴよこのブログ

日々の日記。技術ネタでまとまりきってないものの記録、伝わる文章の書き方を練習とか。

Rubyベストプラクティスで学ぶ Test::Unitの基礎

例外をテストする

  • 例外が発生することをテスト
assert_raises(KeyError) do
  hash.fetch(:doesnt_exists)
end
  • 例外が発生しないことをテスト
assert_nothing_raised do
  hash.fetch(:key_exists)
end

メソッドが意図的にエラーを発生させる時は、エラーを発生させる場合とさせない場合の両方をテストすること。

こうすると、無条件にエラーが発生する訳ではないこと、条件が合えばエラーが発生すること、の両方をテストできる。

高度なテストテクニック

モックとスタブを使う

  • IOを伴うような、ユーザーインターフェース部分と、ロジックを出来る限る分離する
  • ロジックが分離できれば、その部分のテストは簡単になる

ユーザー入力への応答をテストしたければ、スタブを使う

class Questioner
  def method_want_to_test
    ask("Are you happy?") ? "Good I'm Glad" : "That's Too Bad"
  end

  def ask(question)
    # ユーザーからの入力を受け取るなど何か処理をする
    ...
    response = simple_logic
    ...
    # ロジックで判定した結果を元になにか答えを返す
    ...
  end
  
  def simple_logic
      # 何かシンプルなロジックで答えを返す
  end
end

user_interactionを含む ask メソッドの戻り値をテストしたい場合

特異メソッドを使ってaskの戻り値をスタブする

テストケース

def setup
  @questioner = Questioner.new
end

def test_yes_response do
  def @questioner.ask(question); true; end
  assert_equal "Good I'm glad", @questioner.method_want_to_test
end

テストケース内で@questionerインスタンスに特異メソッドを定義している。

元々あるaskをこのインスタンスだけに対して上書きし、必ずtrueを返すようにしている。

その結果テストしたかった"yes"が返って来た場合のレスポンスを簡単にテストできている。

対象のインスタンスのみ、メソッドを上書きしている。 特異メソッド・・すご〜い。。

こんなことして良いんだ。。自由だな〜Ruby

複雑な出力をテストする時

XML等、複雑な出力をテストしたい時、パーサーの利用を検討する。

nokogiriなど、有名なパーサーを用いて、出力結果をパースする。

テスト対象にするのはパーサーの出力。

出力をパースする道具を信用する必要があるが、信頼できるライブラリであれば、出力が単なる文字の固まりではなく、何か意味のある結果を作り出していることの現れである。

Rubyベストプラクティス 1章 テストでコードを駆動する まとめ より

テストに慣れる最善の方法は、まずテストを書き始めるだけだ。それ以外のことは、自然と後からついてくるだろう。

正直、後半の高度なテストに関するところは、自分で繰り出せるほど会得出来たわけじゃないけど、まとめ、の言葉に従ってやり続けていくしかない。