TurboRubyで Test::Unitを使う

By: Chikako Yonezawa

Abstract: TurboRuby上で Test::Unitを使用しユニットテストを行う手順について説明します

TurboRubyや、3rdRailでは、Test::Unit, RSpec, Shouldaなどのフレームワーク(ライブラリ)を使用し、ユニットテストを作成・実行することが可能です。この記事では、TurboRuby上で Test::Unitを使用してユニットテストを実行する手順について説明します。

ユニットテストとは、システムのテスト手法の1つで、個々のモジュールやメソッドなどの小さな単位で行うテストを行うテスト手法です。大規模なプログラムを一度にテストし、問題が発生した場合、その問題を特定するのは非常に困難であり、また、複数の要因が影響して問題が発生している場合もあります。

ソフトウエアテストでは、十分なユニットテストを行った後、結合テストへというように進めていくのが一般的です。

    Test::Unitとは?

Rubyに標準で添付されているクラスライブラリ

Rubyスクリプトのテストを自動化する際の基本的な枠組みとなります。

TurboRubyで Test::Unitを実行するにあたって、テスト元のクラス echoを作成します。

このクラスは、単純に設定された値をそのまま返すだけの echoというメソッドを持ちます。

    Test::Unit実行手順

    1. Rubyプロジェクトの作成

TurboRubyを起動し、メニューの[ファイル|新規|Rubyプロジェクト]を選択して、Rubyプロジェクトを作成します。

プロジェクト名には、任意の名前を指定します。今回は echoProjという名前をつけます。

Rubyインタプリターの設定が行われていない場合は、「インタプリターの構成」のリンク部分をクリックして、使用する Rubyインタプリタを指定します。

詳しい手順につきましては、過去記事となりますが

http://edn.embarcadero.com/article/37231

http://edn.embarcadero.com/article/37243

をご覧ください。(3rdRail/TurboRubyで同一手順です)                        

Hide image
Click to see full-sized image

    2. テスト元のクラスの作成

作成したプロジェクト内に、テスト元のクラスを作成します。

メニューの[ファイル|新規|Rubyクラス]を選択すると、Rubyクラスの新規作成のダイアログが表示されます。ファイル名に任意の名前を入力し、[実行]ボタンを押し、クラスを生成します。

この例では echoと入力します。

Hide image
Click to see full-sized image

    3. テスト元のクラスの実装

上記手順により、Echo.rbが生成され、エディタに echoクラスのコードが表示されます。

初期化の部分と、設定された値をそのまま返すだけの echoという名のメソッドを記述していきます。

echo.rb

class Echo
  def initialize(value)
    @value = value
  end

  def echo
    value = @value
    value
  end
end

Hide image
unittest04

メニューの[ファイル|保管]を選択して、記述したコードを保存します。

    4. 作成したクラスの動作確認

作成したクラスの動作を確認します。

メニューの[ウィンドウ|Rubyコンソール|新規作成]を選択すると、プロジェクトの選択ダイアログが表示されれます。作成した echoProjを選択し、[OK]ボタンをクリックします。

irbが起動しますので、

Hide image
unittest06

と、下線の部分を入力すると、入力した値がそのまま返却されるクラス Echoの echoメソッドが動作することを確認することができます。

しかし、機能拡張などあった際、このようにコマンドでいちいちテストするのは、テスト自体に漏れが発生したりするので、効率的な方法ではありません。

このようなテストプロセスを構造化するためのフレームワークの1つとして Test::Unitがあります。また、Test:Unitを使用する際にはいくつかの約束事があります。

    5. Test::Unitを使用する際の約束事について

    5.1 テストを実行するメソッド名は test_で始まる名前にする

  def test_echo  - - - OK
  def echo_test  - - - NG

    5.2 テストを行う クラスを requireで指定する

  require ‘echo’

    5.3 require ‘test/unit’を記述する

これを記述しないと test::unitのクラスを使用できません。

    5.4 クラスを TestCaseのサブクラスとして定義する

テスト用のクラスに < Test::Unit::TestCase を記述し、Test::Unit::TestCaseのサブクラスとして定義する

    6. テスト用のクラスの作成

それでは、上記で説明した約束事に従ってテスト用のクラスを作成します。

プロジェクトにテスト用のクラスを追加します。メニューより、[ファイル|新規|Rubyクラス]を選択し、このクラスに Test_echoという名前をつけます。

Hide image
Click to see full-sized image

    7. テスト用クラスの実装

約束事に従って、テスト用のクラスを作成していきます。

  # テストを行うクラスを requireで指定
  require ‘echo’
  # reuire ‘test/unit’を記述
  require ‘test/unit’

  # テスト用のクラスに < Test::Unit::TestCaseを記述
  Class Test_echo < Test::Unit::TestCase
  # テストを実行するメソッドは test_で始まる名前にする
    def test_echo
      
    end
  end

Hide image
Click to see full-sized image

    8. 評価メソッドの実装

メソッドの中には、評価のためのメソッドを記述します。Test::Unitはアサーション(assertion)と呼ばれるメソッドにより、「目的とする結果」と「実際のテスト結果」を取得して、「実際のテスト結果」が「目的とする結果」と一致しない場合、メッセージを出力します。

アサーションの種類として主なものを以下に記します。

( 詳しいドキュメントに関しましては、Rubyリファレンスマニュアル等をご参照ください。)

assert(boolean, [message])

booleanが trueなら pass

assert_nil(obj, [message])

objが nilであれば pass

assert_equal(expected, actual, [message])

expected == actualならpass

assert_match(regexp, string, [message])

string =~ regexpが trueなら pass

assert_throws(expected_symbol, [message]) {block}

ブロックを実行して expected_symbolが throwされたら pass

テスト用のクラスに、このアサーションを記述します。

  # テストを行うクラスを requireで指定
  require ‘echo’
  # reuire ‘test/unit’を記述
  require ‘test/unit’

  # テスト用のクラスに < Test::Unit::TestCaseを記述
  Class Test_echo < Test::Unit::TestCase
  # テストを実行するメソッドは test_で始まる名前にする
    def test_echo
      # アサーションを記述 結果が予測されたものであれば pass
      assert_equal(“aaa”, Echo.new(“aaa”).echo, “こちらはOK”)
    end
  end

Hide image
Click to see full-sized image

メニューより[ファイル|保管]を選択して保存します。

    9. テスト実行 (正常実行の場合)

スクリプト・エクスプローラー上の test_echo.rbを選択し、マウスの右ボタンをクリックしてポップアップメニューを表示します。表示されたメニューより[実行|Rubyテスト]を選択して、このユニットテストクラスを実行します。

Hide image
Click to see full-sized image

画面の左にあるワークスペースにスクリプト・テストのタブが追加され、実行結果が表示されます。この場合は予測された結果が返却されているので、何も無かったような結果表示となっています。

Hide image
unittest09

    10. テスト実行 (アサーションの発生)

次に、アサーションが発生する場合を見てみましょう。

先程の Test_echoクラスに、故意にエラーとなる assert_equalを追加します。

  # reuire ‘test/unit’を記述
  require ‘test/unit’

  # テスト用のクラスに < Test::Unit::TestCaseを記述
  Class Test_echo < Test::Unit::TestCase
  # テストを実行するメソッドは test_で始まる名前にする
    def test_echo
      # アサーションを記述 結果が予測されたものであれば pass
      assert_equal(“aaa”, Echo.new(“aaa”).echo, “こちらはOK”)
      assert_equal(“bbb”, Echo.new(“aaa”).echo, “こちらはNG”)
    end
  end

先程と同様に保存して実行します。

今回は、予測された結果と異なる結果となり、アサーションが発生し、障害トレースが表示されます。

Hide image
unittest10

障害トレースのメッセージ部分「こちらはNG」をマウスでダブルクリックすると、結果の比較が表示されます。

Hide image
unittest11

これで、期待される結果と、実際の結果の比較をひと目で確認することが可能ですし、アサーションが発生した地点もすぐに表示することが可能です。

    まとめ

この記事では、Test::Unitを使用してユニットテストを行ないましたが、このようにテストプロセスを構造化することによって、機能変更があっても、効率的で漏れのないテストの実施が可能となります。

Server Response from: ETNASC02