*目次 [#q1036b05]
 
 #contents
 
 *Railsによるテスト作成 [#yb95687b]
 
 http://www.pragmaticprogrammer.com/title/rails/
 の12章「Task T: Testing」と
 http://jp.rubyist.net/magazine/?0013-RubyOnRails
 を参照しながらRailsによるユニットテスト、機能テスト、自動化テストの作成を行ってみる
 
 **準備 [#l95a796f]
 
 スケルトンを作る
 
 # rails gentest
 
 この段階でgentest/test/にはユニットテスト、機能テストのスケルトンも作成されている
 
 # cd gentest/test
 # dir
 
  fixtures/
  functional/
  mocks/
  unit/
  test_helper.rb
 
 fixturesはテスト用データベースの初期化時に初期データとして投入するデータを定義したYAML(*.yml)ファイルを格納するディレクトリ、functionalは機能テストを格納するディレクトリ、mocksはモックを格納するディレクトリ、unitはユニットテストを格納するディレクトリになる。test_helper.rbはテスト用の共通関数、定義置き場。
 
 **モデル定義とテスト作成 [#u7932361]
 
 モデルを定義して、テストを作成する。
 
 ***準備 [#a90f347e]
 
 DBテーブルは下記を使う(テーブル名、カラム名はRailsの規約に従う)
 
  -- books
  create table books (
    id                    integer primary key,
    title                 varchar(255) not null,
    description           text,
    updated_at            datetime
  );
 
 このテーブルスキーマをdb/schema.sqlとして保存し、下記でデータベースを作成する(SQLiteを使用)
 
 # cd db
 # sqlite3 gentest.db < schema.sql
 
 接続情報をconfig/database.ymlに記載する
 
  development:
    adapter: sqlite3
    dbfile: db/gentest.db
 
 モデルクラス(Book)のスケルトンを作成する
 
 # ruby script/generate model Book
 
 この段階で、
 test/unit/book_test.rb
 test/fixtures/books.yml
 が自動作成される
 
 book_test.rbはBookクラス用のユニットテスト、books.ymlはBookモデル用のfixtureになる。
 
 ***最初のテスト実行 [#tfb0883a]
 
 test/unit/book_test.rbは下記のようになっている
 
  require File.dirname(__FILE__) + '/../test_helper'
  
  class BookTest < Test::Unit::TestCase
    fixtures :books
  
    # Replace this with your real tests.
    def test_truth
      assert_kind_of Book, books(:first)
    end
  end
 
 RailsのテストクラスはTest::Unit::TestCaseクラスのサブクラスになっている。[[Test::Unitフレームワーク>http://www.ruby-lang.org/ja/man/?cmd=view;name=Test%3A%3AUnit]]はRailsにバンドルされているので、この段階ですぐにテスト実行してみることができる。
 
 # ruby test/unit/book_test.rb
 
 Railsはtestスクリプトを実行するたびに、テストデータベースを作成し、テストメソッドを実行するたびにfixtureのデータでテストデータベースのデータを初期化する。
 しかし、まだテストデータべースにdb/gentest.dbのスキーマを定義していないので、この検査は失敗する。
 
 テストデータベースのスキーマ定義は下記のrakeコマンドによって実行する
 
 # rake clone_structure_to_test
 
 これで、スキーマだけがテストデータベースに定義される・・・はずなのだが、自分の環境では下記のエラーを吐いて失敗する
 
  rake aborted!
  You have a nil object when you didn't expect it!
  You might have expected an instance of Array.
  The error occured while evaluating nil.[]
 
 ちょっと調べてみたが、原因はまだ不明。
 ので、以下は実際に動作確認なしの情報になる
 
 ***fixture定義 [#z20f23a3]
 
 スケルトン状態ではtest/fixtures/books.ymlの内容は下記の通り
 
  # Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html
  first:
    id: 1
  another:
    id: 2
 
 idだけがデータセットされている状態。
 
 fixtureとして下記を記述する
 
  first:
    id: 1
    title: 基礎からはじめるRuby
    description: 基礎からはじめるRubyの説明
  second:
    id: 2
    title: Effective Java
    desctiption: 〜〜〜〜〜〜〜
 
 ***モデルオブジェクト作成とレコード読み込みのテスト [#m1b5a227]
 
 test/unit/book_test.rbにsetup()、test_create()メソッドを下記のように定義する~
 (Test::Unitはtest_で始まるメソッドを全て自動実行する。またsetup()メソッドは各テストメソッドが呼ばれる前に必ず実行される)
 
   def setup
 	@book = Book.find(1)
   end
   
   def test_create
 	assert_kind_of Book, @book
 	assert_equal 1, @book.id
 	assert_equal "基礎からはじめるRuby", @book.title
 	assert_equal "基礎からはじめるRubyの説明", @book.description
   end
 
 setup()メソッドではidが1のBookレコードを@bookに格納し、各テストメソッドで参照できるようにしている。
 
 test_create()メソッドではまず、@bookがBookモデルのオブジェクトであることを確認し、その後オブジェクトのid、title、descriptonが正しくセットされていることを確認している。
 
 ***レコード更新のテスト [#sfd65f00]
 
 test/unit/book_test.rbにtest_update()メソッドを下記のように定義する。
 
   def test_update
 	assert_equal "基礎からはじめるRuby", @book.title
 	@book.title = "新・基礎からはじめるRuby";
 	assert @book.save @book.errors.full_messages.join("; ")
 	@book.reload
 	assert_equal "新・基礎からはじめるRuby", @book.title
   end
 
 assertメソッドでテストデータベースへの更新が正しく行われることをチェックし、その後reload()メソッドで@bookの状態を更新したら、正しく更新されたことを確認している
 
 ***レコード削除のテスト [#wc379dfa]
 
 test/unit/book_test.rbにtest_destroy()メソッドを下記のように定義する。
 
   def test_destroy
 	@book.destroy
 	assert_raise(ActiveRecord::RecordNotFound) { Book.find(@book.id) }
   end
 
 レコードを削除した後、そのレコードを検索するとActiveRecord::RecordNotFoundのExceptionが発生することをassert_raiseメソッドでチェックしている
 
 ***DRYの導入 [#xddd8c8d]
 
 books.ymlに定義した値(基礎からはじめるRuby等)をテストコード中にまた記述してしまうのはDRY(Don't Repeat Yourself)に反する。
 フレキシビリティを保ちつつ、テストコードを書くには下記のようにする
 
   def test_create
 	assert_kind_of Book, @book
 	# fixture名を指定して取り出すことができる(@bookではなく@booksであることに注意)
 	first_book = @books["first"]
 	assert_equal first_book["id"], @book.id
 	assert_equal first_book["title"], @book.title
 	assert_equal first_book["description"], @book.description
   end
 
 下記のようにすれば、マッチするfixtureを自動で探して値をとってきてくれるのでより楽。(@fixture名_カラム名)
 
 
   def test_create
 	assert_kind_of Book, @book
 	assert_equal @first_id, @book.id
 	assert_equal @first_title, @book.title
 	assert_equal @first_description, @book.description
   end
 
 

トップ   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS

アークウェブのサービスやソリューションはこちら