Ruby-on-rails-2.1-rails-unit-testing

提供:Dev Guides
移動先:案内検索

Ruby on Rails 2.1-単体テスト

前書き

先に進む前に、いくつかの定義を簡単に見てみましょう-

  • テスト-一貫した結果を生成し、Railsアプリケーションが期待どおりに動作することを証明するテストアプリケーションです。 テストは、実際のアプリケーションと同時に開発されます。
  • アサーション-これは、予想される結果のためにオブジェクト(または式)を評価するコードの1行です。 たとえば、この値はその値ですか? このオブジェクトはゼロですか?
  • テストケース-これは、コンテキストに関連するテストで構成されるテスト_ストラテジー_を含むTest :: Unit :: TestCaseから継承されたクラスです。
  • テストスイート-これはテストケースのコレクションです。 テストスイートを実行すると、そのスイートに属する各テストが実行されます。

Railsテスト

ヘルパースクリプト_script/generate_を実行して_controllers_と_models_を作成すると、Railsは単体テストと機能テストのフレームワークを生成します。 作成する機能のテストをフレームワークに入力することで、かなり良いテスト範囲を得ることができます。 Railsアプリケーションでテストする2つの重要なポイントがあります-

  • モデルのテスト
  • コントローラーのテスト

このチュートリアルでは、両方のテストについて簡単に説明します。 概念を理解するために、_testapp_を1つ作成しましょう。

C:\ruby> rails -d mysql testapp

データベースのセットアップ

これまで、Railsアプリケーションの開発データベースのみを使用しましたが、テストデータベースも作成し、config/database.ymlファイルの適切なセクションが正しく設定されていることを確認する必要があります。

次のように開発およびテストデータベースを作成しましょう-

mysql> create database testapp_test;
Query OK, 1 row affected (0.01 sec)

mysql> create database testapp_development;
Query OK, 1 row affected (0.01 sec)

mysql> use testapp_test;
Database changed

mysql> grant all privileges on testapp_test.*
   to 'root'@'localhost' identified by 'password';
Query OK, 0 rows affected (0.00 sec)

mysql> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.00 sec)

database.ymlの構成

次のようにconfig/database.ymlを設定します-

development:
   adapter: mysql
   encoding: utf8
   database: testapp_development
   username: root
   password: password
   host: localhost
test:
   adapter: mysql
   encoding: utf8
   database: testapp_test
   username: root
   password: password
   host: localhost
production:
   adapter: mysql
   encoding: utf8
   database: testapp_production
   username: root
   password: password
   host: localhost

移行を生成する

書籍のタイトル、価格、簡単な説明などを含む表があるとします。 次の移行は、このテーブルを設定します-

testapp > ruby script/generate migration books

今testapp/db/migrate/20080616170315_books.rbファイルを次のように変更します-

class Books < ActiveRecord::Migration
   def self.up
      create_table :books do |t|
         t.string     :title, :limit => 32, :null => false
         t.float      :price
         t.text       :description
         t.timestamp  :created_at
      end
   end

   def self.down
      drop_table :books
   end
end

次のように移行を実行します-

testapp > rake db:migrate

これにより、testapp_developmentデータベースに books テーブルが作成されます。 その後、次のように_rake_コマンドを使用してテストデータベースを設定する必要があります-

C:\ruby\testapp > rake db:test:clone_structure

これにより、_testapp_development_データベースが_testapp_test_データベースに複製されます。 開発データベースにあるものは何でも意味しますが、テストデータベースにも同じデータがあることになります。

モデルのテスト

generateスクリプトを使用して_model_を生成すると、Railsはテストディレクトリにモデルのユニットテストスクリプトも生成します。 また、fixture、testapp_testデータベースにロードされるテストデータを含む_YAML_ファイルを作成します。 これは、ユニットテストの実行対象となるデータです-

testapp > ruby script/generate model Book
   exists  app/models/
   exists  test/unit/
   exists  test/fixtures/
   create  app/models/book.rb
   create  test/unit/book_test.rb
   create  test/fixtures/books.yml
   create  db/migrate
   create  db/migrate/20080616164236_create_books.rb

モデルクラスでコードを記述するとき、これらのファイルに対応するテストを記述します。 次のようにtest/fixtures/books.ymlでYAMLを使用して2つのテストブックレコードを作成しましょう-

perl_cb:
   id: 1
   title: 'Ruby Tutorial'
   price: 102.00
   description : 'This is a nice Ruby tutorial'
java_cb:
   id: 2
   title: 'Java Programming'
   price: 62.00
   description : 'Java Programming for the beginners'

今、本ユニットテストファイルtest/unit/book_test.rbの既存のコードを次のコードに置き換えましょう-

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

class BookTest < ActiveSupport::TestCase
   fixtures :books

   def test_book

      perl_book = Book.new :title => books(:perl_cb).title,
         :price => books(:perl_cb).price,
         :description => books(:perl_cb).description,
         :created_at => books(:perl_cb).created_at

      assert perl_book.save

      perl_book_copy = Book.find(perl_book.id)

      assert_equal perl_book.title, perl_book_copy.title

      perl_book.title = "Ruby Tutorial"

      assert perl_book.save
      assert perl_book.destroy
   end
end

最後に、次のようにテストメソッドを実行します-

testapp > ruby test/unit/book_test.rb

ここに成功したテストケースを実行する出力があります-

testapp > ruby test/unit/book_test_crud.rb
Loaded suite ./test/unit/book_test
Started
.
Finished in 0.0625 seconds.

1 tests, 4 assertions, 0 failures, 0 errors

ここで何が起こったのか分析しましょう-

  • BookTestメソッドは、テキストフィクスチャ/books.ymlの最初のレコードのタイトルと他のフィールドを使用して新しいBookオブジェクトを作成することから始めます。 結果のオブジェクトは、perl_bookインスタンス変数に格納されます。
  • Bookオブジェクトの保存が成功したことを示す最初のアサーションテスト。
  • 次に、_find_メソッドを使用してブックオブジェクトを取得し、perl_book_copyという名前の別のインスタンス変数に格納します。 この取得の成功は、両方の書籍オブジェクトのタイトルを比較する次のアサーションでテストされます。 この時点で、データベースレコードを作成して読み取る機能をテストしました。
  • ソリューションは、perl_bookに格納されているオブジェクトに新しいタイトルを割り当てることで更新をテストし、変更の保存が成功したことをアサートします。
  • 最後に、Bookオブジェクトを破棄する機能がテストされます。

これが、Railsモデルをテストする方法です。

コントローラーのテスト

コントローラのテストは「機能テスト」としても知られています。 機能テストは、コントローラの次のタイプの機能をテストします-

  • 応答は期待どおりにリダイレクトされますか?
  • 予想されるテンプレートはレンダリングされていますか?
  • ルーティングは期待通りですか?
  • 応答に予期されるタグが含まれていますか?

Railsフレームワークは5種類のリクエストをサポートしています-

  • get
  • post
  • put
  • head
  • 削除する

機能テストを作成するには、コントローラーが処理する5つのHTTP要求タイプのいずれかをシミュレートする必要があります。

要求タイプ「get」および「post」は、コントローラーのテストで最も一般的に使用されています。 これらのすべてのメソッドは4つの引数を取ります-

  • コントローラーのアクション
  • 要求パラメーターのオプションのハッシュ
  • オプションのセッションハッシュ
  • オプションのフラッシュハッシュ

このチュートリアルでは、 get メソッドを使用してコントローラーをテストする方法を説明します。 同様の方法で残りのメソッドをテストできます。

generateで_controller_を生成すると、Railsは次のようにコントローラーの機能テストスクリプトを作成します-

testapp > ruby script/generate controller Book
   exists  app/controllers/
   exists  app/helpers/
   create  app/views/book
   exists  test/functional/
   create  app/controllers/book_controller.rb
   create  test/functional/book_controller_test.rb
   create  app/helpers/book_helper.rb

コントローラークラスにコードを記述すると、これらのファイルに対応するテストを記述します。 その前に、次のように app/controllers/book_controller.rb 内でコントローラー関数_list、show、_および_search_を定義しましょう-

class BookController < ApplicationController
   def list
      @book_pages, @books = paginate :books, :per_page => 10
   end

   def show
      @book = Book.find(params[:id])
   end

   def search
      @book = Book.find_by_title(params[:title])
      if @book
         redirect_to :action => 'show', :id => @book.id
      else
         flash[:error] = 'No such book available'
         redirect_to :action => 'list'
      end
   end
end

- show および_list_メソッドには2つのビューテンプレートが必要です。 これらのビューを定義してテストすることはできますが、今はこれらのビューを定義せずに続行します。

次のように test/fixtures/books.yml ファイルにあるテストフィクスチャを再利用しましょう-

perl_cb:
   id: 1
   title: 'Ruby Tutorial'
   price: 102.00
   description : 'This is a nice Ruby tutorial'
java_cb:
  id: 2
  title: 'Java Programming'
  price: 62.00
  description : 'Java Programming for the beginners'

次の_test_search_book_および_test_search_not_found_メソッドを_test/functional/book_controller_test.rb_に追加して、Book Controllerの検索アクションの機能をテストします。

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

# Re-raise errors caught by the controller.
class BookController
   def rescue_action(e)
      raise e
   end
end

class BookControllerTest < Test::Unit::TestCase
   fixtures :books
   def setup
      @controller = BookController.new
      @request    = ActionController::TestRequest.new
      @response   = ActionController::TestResponse.new
   end

   def test_search_book
      get :search, :title => 'Ruby Tutorial'
      assert_not_nil assigns(:book)
      assert_equal books(:perl_cb).title, assigns(:book).title
      assert_valid assigns(:book)
      assert_redirected_to :action => 'show'
   end

   def test_search_not_found
      get :search, :title => 'HTML Tutorial'
      assert_redirected_to :action => 'list'
      assert_equal 'No such book available', flash[:error]
   end
end

次のようにテストケースを実行します-

testapp > ruby test/functional/book_controller_test.rb

それは次の出力を与えます-

Loaded suite test/functional/book_controller_test
Started
..
Finished in 0.422 seconds.

2 tests, 7 assertions, 0 failures, 0 errors

ここで何が起こったのか分析しましょう-

  • _setup_メソッドは、コントローラー、要求、および応答オブジェクトを作成するデフォルトのメソッドです。 Railsによって内部的に使用されます。
  • 最初のテストメソッド_test_search_book_は、検索アクションへの get リクエストを生成し、_title_パラメーターを渡します。
  • 次の2つのアサーションは、Book_オブジェクトが @ book_というインスタンス変数に保存されたこと、およびオブジェクトが存在する可能性のあるActive Record検証に合格したことを検証します。
  • 最初のメソッド内の最後のアサーションは、リクエストがコントローラーのshowアクションにリダイレクトされたことをテストします。
  • 2番目のテストメソッド_test_search_not_found_は、別の_get_要求を実行しますが、無効なタイトルを渡します
  • 最初のアサーションは、_list_アクションへのリダイレクトが発行されたことをテストします。
  • 進行中のアサーションが成功した場合、_flash_ハッシュにメッセージがあり、assert_equalでテストできます。

アサーションの詳細については、http://guides.rubyonrails.org/api_documentation_guidelinesl [Rails標準ドキュメント]を参照してください。

テストにRakeを使用する

*rake* ユーティリティを使用して、アプリケーションをテストできます。 以下にいくつかの重要なコマンドのリストを示します。
  • $ rake test -すべての単体テストと機能テスト(および存在する場合は統合テスト)をテストします。
  • * $ rake test:functionals *-すべての機能テストを実行します。
  • $ rake test:units -すべての単体テストを実行します。
  • $ rake test:integration -すべての統合テストを実行します。
  • $ rake test:plugins -./vendor/plugins/**/testですべてのテストを実行します。
  • $ rake test:recent -過去10分間に変更されたモデルとコントローラーのテストを実行します-
  • $ rake test:uncommitted -Subversionのプロジェクトの場合、最後のコミット以降にモデルとコントローラーで行われた変更のテストを実行します-