2

作为 TDD 和 Rails 世界的新手,我试图弄清楚如何减少我的规范的运行时间。

我放弃了 Rails 框架的加载,只加载了 ActiveRecord 部分。这有很大帮助(-8s),尽管我仍然想知道是否还有更多我可以做的。

spec 文件有 5 个示例,运行它time rspec path_to_spec.rb需要 1.7 秒。当我删除 FactoryGirl 并Project.create改为使用时,我达到了 1.4 秒。

我要测试的是模型的范围和查询组合是否正常。我不确定在这种情况下是否可以使用模拟/存根。

  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

除了调整您的数据库以尝试使其运行得更快之外,由于许多附带严重次优的默认配置,这只是您必须处理的事情之一。不过,有一些事情可以提供帮助。

Ruby 1.9.3 在初始化 Rails 环境方面比以前的版本快很多,所以你使用它很好。过去,在某些机器上,仅仅为了调出控制台就需要大约 20 秒。由于一些内部优化,最近有所改善。

不过,不要指望您的单元测试会立即运行。几秒钟通常没什么大不了的。如果可以,运行重点测试,即一次一种测试方法,然后是整个测试模块,然后是整个测试套件。有许多流行编辑器的插件可以帮助解决这个问题。

好消息是 Rails 4 正在做一些工作以建立更持久的测试过程,但尚不清楚这是否会在发布版本中。

于 2013-01-03T22:12:06.713 回答