【Rails:5】テスト

テストとは

  • テスト
    アプリケーション開発において、ソフトウェアが正しく機能するかどうか調べる作業。
    テストスクリプトには、仕様書/設計書としての役割もあります。
    railsではテストが重視されており、テストに必要な機能が用意されています。
    • 単体テスト(test\unit以下)
      モデル・ヘルパーのテスト。
    • 機能テスト(test\functional以下)
      コントローラのテスト。
    • 統合テスト(test\integration以下)
      実際のリクエストをシミュレーションするテスト。
  • テスト駆動開発
    機能を実装する前にテストを書き、テストが通るようにコーディングしていく開発スタイル。
    1. テストを書く
    2. テストが失敗することを確認する
    3. テストが通るように実装する
    4. テストが通る状態を維持したままリファクタリング

テストの準備

  • テスト用データベースの作成
    • テスト用データベースのスキーマ定義
      開発用データベースのスキーマ定義をテスト用データベースにコピーします。
$ rake db:test:prepare

または

$ rake db:test:clone
config.active_record.schema_format = :sql
    • フィクスチャファイル作成
      test\fixtures\データベース名.yml
      ここに記述した内容が、テスト用データベースの初期状態になります。
      テストを実行するたびにフィクスチャが読み込まれ、初期状態に戻ります。

テストの実行

  • 1つずつ実行
$ ruby test\unit\mdl_name_test.rb
$ ruby test\functional\ctl_name_controller_test.rb
    • 特定のテストメソッドのみ実行
$ ruby test\unit\mdl_name_test.rb --name=test_truth
$ ruby test\unit\mdl_name_test.rb -n test_truth
$ rake test:units
    • 機能テストをまとめて実行
$ rake test:functionals
    • 統合テストをまとめて実行
$ rake test:integration
    • すべてのテストをまとめて実行
$ rake test
$ rake
# rakeコマンドで実行する場合、テストの前に rake:db:prepare も実行される

テストの記述

require File.dirname(__FILE__) + '/../test_helper.rb'

class MdlNameTest < Test::Unit::TestCase
  fixtures :mdlnames

  def test_truth
    assert true
  end
end
  • テストメソッド
    テストスクリプト内にtest_**という名前のメソッドを記述すると、それがテストメソッドとして実行されます。
  • アサーション
    ある条件が成立しているかを確認すること。
    各種アサーションメソッドは、引数の条件式がtrueなら何もせず、falseなら警告を表示します。
    コンソールからテストを実行すると、以下を確認できます。
    • * tests::テストメソッドの数
    • * assertions::アサーションメソッドの数
    • * failures::失敗したアサーションの数
    • * errors::テストメソッドのバグやデータベースエラーの数
アサーションメソッド 成功する条件
assert a a
assert_equal 期待する値, アサートしたいオブジェクト 期待する値 == アサートしたいオブジェクト
assert_not_equal a != b
assert_nil a a == nil
assert_not_nil a != nil
assert_kind_of クラス名, a a.class == クラス名
assert_match 正規表現パターン, a (正規表現パターン =~ a) != nil
assert_not_match 正規表現パターン, a (正規表現パターン =~ a) == nil
assert_raise(例外の種類) {例外を起こすメソッド} スクリプトが特定の例外を発生させる
  • テストする値
    テストでアサートすべき値は、次の3種類に限られます。
    必要以上にテストを書くべきではありません。
    • 正常値
    • 境界値(もっとも端の正常値)
    • 異常値(複数存在する場合もある)
  • setupメソッド
    すべてのテストメソッドの実行前に呼び出されるメソッド。
    変数の初期化などに利用できます。

単体テスト

  • テストすべきこと
    • レコードのCRUD(作成・読み込み・更新・削除)はできるか
    • 検証は正しく働くか
    • モデルメソッドは正しく働くか etc.
  • 使用するフィクスチャファイルの指定
fixtures :mdlnames, :hoges, :fugas
                  # 他テーブルも使用する場合は追記
# mdlnames.yml
obj1:
  id: 1
  name: オブジェクト1
obj2:
  id: 2
  name: オブジェクト2
obj = mdlnames(:obj1)
obj = @obj2   # test_helper.rb で use_instantiated_fixtures の値を true にしていれば使用可
              # 使用するすべてのフィクスチャでレコード名が重複しないよう注意

機能テスト

  • setupメソッドの中身
    • @controller::コントローラ
    • @request::テスト用リクエス
    • @response::テスト用レスポンス
  • アクションの呼び出し
def test_action1
  get :action1,   # HTTPメソッド&アクション名
      :id => 2    # パラメータ
end

def test_action2
  post :action2,
       :id => 2,
       :name => "hoge"
end
アサーションメソッド trueになる条件
assert_response a サーバのレスポンスがa
assert_redirected_to :controller => 'ctr_name', :action => 'action1' ctr_name/action1にリダイレクト
assert_template 'ctr_name/action1' テンプレートがctr_name/action1.rhtml
assigns(:objname)
  assert_match "hoge", @response.body
  assert_equal true, @response.body.include?("hoge")
# assert_equal "hoge", flash.now[:notice] とはできない
  • レンダリングのテスト
    • assert_selectメソッド
      HTMLの要素をテストします。
      引数によって、要素の存在・値・数・属性・親子関係などをアサートします。
    • find_tag, find_all_tagメソッド
      レンダリングされたHTML全体から特定の要素を検索します。
  • 使用するフィクスチャファイルの指定
fixtures :mdlnames, :hoges, :fugas