【Rails】【test】fixturesファイルの読込に関してのまとめ

Railsでテストを実行する時に、fixturesが読み込まれる、読み込まれないのタイミングがあいまいだったので色々と実験して得られた結果をもとにまとめていきます。

Railsでテストを実行する方法

  • rubyコマンドでテストファイル名を直接指定して実行する
  • Rakeコマンドで実行する
rubyコマンドで直接実行
例)test/unit/user_test.rbを実行する
ruby test/unit/user_test.rb
rakeコマンドで実行
  • 複数のテストをまとめてテストする時のためのRakeタスクが存在します。
    • rake db:test:prepare
    • rake test
    • rake test:functionals
    • rake test:units
    • rake test:recent

テストデータの用意の仕方

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

class UserTest < ActiveSupport::TestCase
  fixtures :users, :schools #users.ymlとschools.ymlが読み込まれます

  def test_get_active
  (略)
  end
end

rubyコマンドで実行したテストとrakeコマンドで実行した時の結果が違うんだけど…?

ここで躓く原因はrailsでのテストの挙動の理解とrakeコマンドへの理解が足りていないためだと思われます。

railsでのテストの挙動の理解
  • railsでテストを走らせる場合、テストDBを参照して行われます。
  • テストDBはrake db:test:prepareコマンドで、development環境のDBからスキーマをコピーして、生成されます。
  • それぞれのtableの中身のデータはtestファイル内にfixtures宣言を書いてあげることで読み込まれます。
  • さらに、rakeコマンドでテストを実行された場合、1度読み込まれたfixturesはテストDBにデータが入ったまま次のテストが実行されていきます。
  • よってテストファイルが読み込まれる順番が違うためにエラーが起きるといったこともありえます。
  • これをなくすためには、テストファイル内で扱うデータはfixtures宣言で再読みこみすることだと思います。
rakeコマンドへの理解
  • まず、rakeコマンドでどんなことが出来るか?それはrake --task(rake -T)で確認することができます。
rake db:fixtures:load          # Load fixtures into the current environment's database.
rake db:migrate                # Migrate the database through scripts in db/migrate.
rake db:schema:dump            # Create a db/schema.rb file that can be portably used against any DB supported by AR
rake db:schema:load            # Load a schema.rb file into the database
rake db:sessions:clear         # Clear the sessions table
rake db:sessions:create        # Creates a sessions table for use with CGI::Session::ActiveRecordStore
rake db:structure:dump         # Dump the database structure to a SQL file
rake db:test:clone             # Recreate the test database from the current environment's database schema
rake db:test:clone_structure   # Recreate the test databases from the development structure
rake db:test:prepare           # Prepare the test database and load the schema
rake db:test:purge             # Empty the test database
rake doc:app                   # Build the RDOC HTML Files
rake doc:clobber_app           # Remove rdoc products
rake doc:clobber_plugins       # Remove plugin documentation
rake doc:clobber_rails         # Remove rdoc products
rake doc:plugins               # Generate documation for all installed plugins
rake doc:rails                 # Build the RDOC HTML Files
rake doc:reapp                 # Force a rebuild of the RDOC files
rake doc:rerails               # Force a rebuild of the RDOC files
rake log:clear                 # Truncates all *.log files in log/ to zero bytes
rake rails:freeze:edge         # Lock to latest Edge Rails or a specific revision with REVISION=X (ex: REVISION=4021) or a tag with TAG=Y (ex: TAG=rel_1-1-0)
rake rails:freeze:gems         # Lock this application to the current gems (by unpacking them into vendor/rails)
rake rails:unfreeze            # Unlock this application from freeze of gems or edge and return to a fluid use of system gems
rake rails:update              # Update both configs, scripts and public/javascripts from Rails
rake rails:update:configs      # Update config/boot.rb from your current rails install
rake rails:update:javascripts  # Update your javascripts from your current rails install
rake rails:update:scripts      # Add new scripts to the application script/ directory
rake stats                     # Report code statistics (KLOCs, etc) from the application
rake test                      # Test all units and functionals
rake test:functionals          # Run tests for functionalsdb:test:prepare / Run the functional tests in test/functional
rake test:integration          # Run tests for integrationdb:test:prepare / Run the integration tests in test/integration
rake test:plugins              # Run tests for pluginsenvironment / Run the plugin tests in vendor/plugins/**/test (or specify with PLUGIN=name)
rake test:recent               # Run tests for recentdb:test:prepare / Test recent changes
rake test:uncommitted          # Run tests for uncommitteddb:test:prepare / Test changes since last checkin (only Subversion)
rake test:units                # Run tests for unitsdb:test:prepare / Run the unit tests in test/unit
rake tmp:cache:clear           # Clears all files and directories in tmp/cache
rake tmp:clear                 # Clear session, cache, and socket files from tmp/
rake tmp:create                # Creates tmp directories for sessions, cache, and sockets
rake tmp:pids:clear            # Clears all files in tmp/pids
rake tmp:sessions:clear        # Clears all files in tmp/sessions
rake tmp:sockets:clear         # Clears all files in tmp/sockets
  • 重要なのは、rake testrake test:functionalsrake test:unit
  • rake test:functionalsでは、rake db:test:prepareをした後に、test/functional以下に存在するファイルを実行すると書いてあります。
  • さらにrake test:unitsでも、rake db:test:prepareをした後に、test/unit以下に存在するファイルを実行すると書いてあります。
  • 要は、都度テストDBをinitializeしていることになります。
  • しかし、rake testを実行するとunitテストが走ってfunctionalテストが走るのですが、rake db:test:prepareが呼び出されるのは初めの1度のみです。
  • これもrubyコマンドでテストを実行した時とrakeコマンドでテストを実行した時の挙動の違いを生む原因かなと思います。
まとめ
  • rakeコマンドは自分が思っていたより多機能。もっと色々な機能があるっぽい。
  • rake doc:qppを実行した時に、なんとなくの仕様書がHTMLベースで生成できたことには感動しました。なんだかrakeコマンドで色んな事できそうで楽しそうです。

最後までお読み下さり、ありがとうございました。

Railsレシピブック 183の技

Railsレシピブック 183の技