2

TDD と Rails の世界の初心者である私は、仕様の実行時間を短縮する方法を見つけようとしています。

Rails フレームワークの読み込みをやめて、ActiveRecord 部分だけを読み込みます。これは非常に役に立ちました (-8 秒) が、他にできることがあるかどうかはまだ疑問に思っています。

スペック ファイルには 5 つの例があり、実行にtime rspec path_to_spec.rbは 1.7 秒かかります。FactoryGirlを外してProject.create代わりに使ったら1.4sになりました。

テストしたいのは、モデルのスコープとクエリの組み合わせが正常に機能するかどうかです。この場合、モッキング/スチューブを使用できるかどうかはわかりません。

  1. たとえば、next_projectの動作をテストするためにモック/スタブ機能を利用する方法はありますか?
  2. ActiveRecord インタラクション タイミングの制限を知るにはどうすればよいですか? つまり、ActiveRecord モデルをテストするときに 1 ~ 2 秒の実行時間に対処しなければならないのでしょうか?
  3. どうすればスピードアップできるかについて、他に提案はありますか?

Ruby 1.9.3、rspec 2.1.12、ActiveRecord 3.2.9 を使用しています

私のモデルファイル:

class Project < ActiveRecord::Base
  default_scope where(:is_enabled => true).order(:position)

  def self.by_slug(slug)
    where(:slug => slug).first
  end
  def find_neighbors
    Neighbors.new(previous_project, next_project)
  end

private
  def previous_project
    Project.where("position < ?", position).last
  end
  def next_project
    Project.where("position > ?", position).first
  end
end

Neighbors = Struct.new(:previous, :next)

私の仕様ファイル:

require 'active_record'
require 'yaml'
require 'factory_girl'
require './app/models/project'
dbconfig = YAML::load(File.open('./config/database.yml'))
ActiveRecord::Base.establish_connection(dbconfig["test"])

FactoryGirl.define do
  factory :project do
    slug { name.parameterize }
    sequence(:position, 1)
    is_enabled true
  end
end

describe Project do
  before(:all) do
    @first_project           = FactoryGirl.create(:project, name: "First Project")
    @second_project_disabled = FactoryGirl.create(:project, name: "Second Project", is_enabled: false)
    @third_project           = FactoryGirl.create(:project, name: "Third Project")
    @fourth_project_disabled = FactoryGirl.create(:project, name: "Fourth Project", is_enabled: false)
    @fifth_project           = FactoryGirl.create(:project, name: "Fifth Project")
  end
  after(:all) do
    projects = [@first_project, @second_project_disabled, @third_project, @fourth_project_disabled, @fifth_project]
    projects.each { |p| p.delete }
  end

  context "when requesting a project by URL slug" do
    it "should return that project if it is enabled" do
      Project.by_slug(@third_project.slug).should eql(Project.find(@third_project.id))
    end
    it "should not return the project if it is not enabled" do
      Project.by_slug(@fourth_project_disabled.slug).should be_nil
    end
  end
  context "when getting first project" do
    it "should have a reference only to the next project enabled" do
      neighbors = @first_project.find_neighbors
      neighbors.previous.should be_nil
      neighbors.next.should eql(Project.find(@third_project.id))
    end
  end

  # 2 more examples similar to the last one
end
4

1 に答える 1

3

データベースをチューニングして高速に実行できるようにすることは別として、多くの場合、デフォルト構成が非常に最適化されていない状態で出荷されているため、対処しなければならないことの 1 つにすぎません。ただし、役立つことがいくつかあります。

Ruby 1.9.3 は、Rails 環境の初期化が以前のバージョンよりもはるかに高速になっているので、それを使用していると便利です。一部のマシンでは、コンソールを起動するだけで 20 秒ほどかかっていました。これは、いくつかの内部最適化により最近改善されました。

それでも、単体テストがすぐに実行されるとは思わないでください。通常、数秒は大した問題ではありません。可能な場合は、焦点を絞ったテストを実行します。つまり、一度に 1 つのテスト メソッドを実行し、次にテスト モジュール全体、次にテスト スイート全体を実行します。これに役立つ一般的なエディタ用のプラグインが多数あります。

良いニュースは、Rails 4 でより永続的なテスト プロセスを作成する作業が行われていることですが、これがリリース バージョンに含まれるかどうかは明らかではありません。

于 2013-01-03T22:12:06.713 に答える