Rails開発でリポジトリには入れたくないんだけどローカルではやっておきたいテストがある場合の取りあつかい

Rails開発でリポジトリには入れたくないんだけどローカルではやっておきたいテストがある場合の取りあつかい

自明だったり、すごく重かったり、細かすぎるテストたちがいます。

重いテストは短期的にも長期的にもコストになり、細かすぎるテストは実装変更時のコストが必要以上に高く、よくありません。

しかし、たまにやっときたいんですよというテストがありますので、本体に影響がないようにやっていきます。

Railsのディレクトリの外にもう一層つくる

以下のような構成になりました。

- /my_test
  - /.git
  - /rails_application # 本体
  - /seed              # テスト用の
  - /spec              # 自分専用テスト
    - /models
    - rails_helper.rb  # 自分専用のテストのrails_helper.rb
  - .gitignore         # 本体を含めないため
  - Gemfile            # 自分専用テスト用のGemfile

自分だけが使うGemを用意する

テストで使いたいが、該当アプリのGemfileに入っていないので使えないGemというのがありますので、どうにかします。(今回のはテストで使う!というGemではないですが)

むりくりrequireしても、コンテキストが変わってしまい、ダメなようですので、本体のGemfileの内容をinstance_evalします。

instance_eval(File.read(File.expand_path('../rails_application/Gemfile', __FILE__)))

# 好きなGemを入れる
gem 'seed-fu'

seed-fu

ところで、ダミーデータもまた、大量だったり詳細だったりすると、コストになります。

しかしさまざまなレコード状態表示の調整をする場合など、ある局面では役に立つので、テスト以外でも使えるように用意しておきます。

#!/usr/bin/env ruby
require File.expand_path('../../rails_application/config/application', __FILE__)
abort("The Rails environment is running in production mode!") if Rails.env.production?
Rails.application.require_environment!

require 'seed-fu'

10000.times do |n|
  ModelA.seed(
    id: n,
    name: SecureRandom.hex(4)
  )
end
$ bundle exec ./seed/seed.rb 

これで外側から、自分のデベロップメントや、テストに、大量のダミーデータを投入できるようになりました。

テスト

rails_helper.rbをコピペして編集する

environmentspec_helperに対するパス部分を本体のファイルに当たるように変更します。

require File.expand_path('../../rails_application/config/environment', __FILE__)
require File.expand_path('../../rails_application/spec/spec_helper', __FILE__)

さきのseed-fuを利用する

seed-fuconfig.before :all内などに書いておけば安泰ではないでしょうか。DatabaseCleanerなどを使っている場合は、それが動いた後である必要があります。

require File.expand_path('../seed/seed', __FILE__)

実行

require 'rails_helper'

RSpec.describe ModelA, type: :model do
  it { expect(ModelA.create!).to be_a(ModelA) }
  it { expect(ModelA.count).to eq(10000) }
end
$ rspec -cfd

# 略

  should be a kind of ModelA(id: integer, name: string, created_at: datetime, updated_at: datetime)
  should eq 10000

Finished in 1 minute 41.39 seconds (files took 3.8 seconds to load)
2 examples, 0 failures

できました。

これはジョークのようなテストですが、たとえばCapybaraでスクリーンショットを撮りまくるといった、半分趣味のようなテストも、本体に影響なくどんどんやっていくことができます。