简体   繁体   English

为什么我在ONE型号上进行rspec Rails测试需要10分钟? (Rails 3.2 / rspec 2 / Guard / spork)

[英]Why do my rspec Rails tests on ONE model is taking 10 minutes ?! (Rails 3.2/rspec 2/Guard/spork)

I have rspec tests defined in my app but they are taking ages! 我在我的应用程序中定义了rspec测试,但是它们已经花了很多年了! In my whole app, I have 438 tests running in 37 minutes. 在我的整个应用程序中,我在37分钟内运行了438个测试。 That's only 10 tests per minute. 每分钟只有10次测试。

I use Guard for rspec, Spork so I think it should be much faster. 我将Guard用作rspec,Spork,所以我认为它应该更快。 there must be something wrong going on. 一定有什么不对劲。

For example, the rspec test on the model 'Prize' is taking 13 minutes for 134 tests. 例如,模型“ Prize”上的rspec测试需要134分钟进行13分钟的测试。 It is terribly slow! 太慢了! Here is my spec for Prize: 这是我对奖品的说明:

require 'spec_helper'

describe Prize do
  let(:admin_user) { FactoryGirl.create(:admin_user) }

  before(:each) do
    @attr = {
      prize_name: "lorem ipsum",
      prize_short_description_for_modals: "yokoko gygy gygy",
      prize_long_description_for_rules_and_user_account:  "longer better longer better longer better",
      prize_detailed_webpage_url: "http://www.example.com",
      prize_image_url: "http://www.example2.com",
      prize_image_alt:"French",
      prize_type: "Jackpot prize",
      prize_initial_stock_quantity: 100,
      prize_remaining_stock_quantity: 5,
      prize_unit_certified_market_value:  450,
      prize_date_for_certified_market_value: 2.days.from_now,
      prize_displayed_value_on_website: 456,
      prize_require_additional_user_info: true,
      prize_max_nb_days_for_claiming: 24,
      prize_expiry_date: 75.days.from_now,
      prize_category: "computer",
      prize_sourcer_company_name: "Nefertiti",
      prize_sourcer_contact_point_name: "Gentle Man",
      prize_sourcer_contact_point_direct_phone: "01 45 67 68 77",
      prize_sourcer_contact_point_email: "gentle.man@example.com",
      prize_sourcer_how_to_contact_details: "From 9 TO 5pm, Mon. to Fri.",
      prize_sourcer_crm_profile_url: "http://www.example3com",
      prize_fully_stocked_validated:  true,
      # admin_user_id: 1,
      # as: :admin_user
    }
  end

    it { should respond_to(:prize_name) }
    it { should respond_to(:prize_short_description_for_modals) }
    it { should respond_to(:prize_long_description_for_rules_and_user_account) }
    it { should respond_to(:prize_detailed_webpage_url) }
    it { should respond_to(:prize_image_url) }
    it { should respond_to(:prize_image_alt) }
    it { should respond_to(:prize_type) }
    it { should respond_to(:prize_initial_stock_quantity) }
  it { should respond_to(:prize_remaining_stock_quantity) }
  it { should respond_to(:prize_unit_certified_market_value) }
  it { should respond_to(:prize_date_for_certified_market_value) }
  it { should respond_to(:prize_displayed_value_on_website) }
  it { should respond_to(:prize_require_additional_user_info) }
  it { should respond_to(:prize_max_nb_days_for_claiming) }
  it { should respond_to(:prize_expiry_date) }
  it { should respond_to(:prize_category) }
  it { should respond_to(:prize_sourcer_company_name) }
  it { should respond_to(:prize_sourcer_contact_point_name) }
  it { should respond_to(:prize_sourcer_contact_point_direct_phone) }
  it { should respond_to(:prize_sourcer_contact_point_email) }
  it { should respond_to(:prize_sourcer_how_to_contact_details) }
  it { should respond_to(:prize_sourcer_crm_profile_url) }
  it { should respond_to(:prize_fully_stocked_validated) }

    it { should respond_to(:admin_user_id) }
    it { should respond_to(:deal_id) }
    # its(:admin_user) { should == admin_user }

    # it { should be_valid }

  # it "should create a new instance given a valid attribute" do
  #   prize.create!(@attr)
  # end

  # -- Active Records Tests --------------------------------------------------------
  describe "tests on prize's active record" do
    it { should belong_to(:admin_user).with_foreign_key('admin_user_id')  }
    it { should belong_to(:deal) }
  end

  # Tests on Mass-Assginement
    describe "tests on prize's attributes mass assignement" do
      it { should allow_mass_assignment_of(:prize_name) }
      it { should allow_mass_assignment_of(:prize_short_description_for_modals) }
      it { should allow_mass_assignment_of(:prize_long_description_for_rules_and_user_account) }
      it { should allow_mass_assignment_of(:prize_detailed_webpage_url) }
      it { should allow_mass_assignment_of(:prize_image_url) }
      it { should allow_mass_assignment_of(:prize_image_alt) }
      it { should allow_mass_assignment_of(:prize_type) }
      it { should allow_mass_assignment_of(:prize_initial_stock_quantity) }
      it { should allow_mass_assignment_of(:prize_remaining_stock_quantity) }
      it { should allow_mass_assignment_of(:prize_unit_certified_market_value) }
      it { should allow_mass_assignment_of(:prize_date_for_certified_market_value) }
      it { should allow_mass_assignment_of(:prize_displayed_value_on_website) }
      it { should allow_mass_assignment_of(:prize_require_additional_user_info) }
      it { should allow_mass_assignment_of(:prize_max_nb_days_for_claiming) }
      it { should allow_mass_assignment_of(:prize_expiry_date) }
      it { should allow_mass_assignment_of(:prize_category) }
      it { should allow_mass_assignment_of(:prize_sourcer_company_name) }
      it { should allow_mass_assignment_of(:prize_sourcer_contact_point_name) }
      it { should allow_mass_assignment_of(:prize_sourcer_contact_point_email) }
      it { should allow_mass_assignment_of(:prize_sourcer_contact_point_direct_phone) }
      it { should allow_mass_assignment_of(:prize_sourcer_how_to_contact_details) }
      it { should allow_mass_assignment_of(:prize_sourcer_crm_profile_url) }
      it { should allow_mass_assignment_of(:prize_fully_stocked_validated) }

      it { should_not allow_mass_assignment_of(:admin_user_id) }
      it { should_not allow_mass_assignment_of(:deal_id) }

      it { should allow_mass_assignment_of(:admin_user_id).as(:admin_user) }
      it { should allow_mass_assignment_of(:deal_id).as(:admin_user) }
    end

  # -- Controller Tests --------------------------------------------------------
  describe "tests on prize's controllers" do
  end

  # -- Models Tests --------------------------------------------------------
  describe "tests on prize's models validations for prize_name" do
    it { should validate_presence_of(:prize_name) }
    it { should_not allow_value(" ").for(:prize_name) }

    it "should reject prize with names that are too long" do
      long = "a" * 101
      hash = @attr.merge(:prize_name => long)
      Prize.new(hash).should have(1).error_on(:prize_name)
    end

    it "should reject prize with names that are too short" do
      short = "a" * 4
      hash = @attr.merge(:prize_name => short)
      Prize.new(hash).should have(1).error_on(:prize_name)
    end
  end

  describe "tests on prize's models validations for prize_short_description_for_modals" do
    it { should validate_presence_of(:prize_short_description_for_modals) }
    it { should_not allow_value(" ").for(:prize_short_description_for_modals) }

    it "should reject attribute that are too long" do
      long = "a" * 301
      hash = @attr.merge(:prize_short_description_for_modals => long)
      Prize.new(hash).should have(1).error_on(:prize_short_description_for_modals)
    end

    it "should reject attribute that are too short" do
      short = "a" * 9
      hash = @attr.merge(:prize_short_description_for_modals => short)
      Prize.new(hash).should have(1).error_on(:prize_short_description_for_modals)
    end
  end

  describe "tests on prize's models validations for prize_long_description_for_rules_and_user_account" do
    it { should validate_presence_of(:prize_long_description_for_rules_and_user_account) }
    it { should_not allow_value(" ").for(:prize_long_description_for_rules_and_user_account) }

    it "should reject attribute that are too long" do
      long = "a" * 10001
      hash = @attr.merge(:prize_long_description_for_rules_and_user_account => long)
      Prize.new(hash).should have(1).error_on(:prize_long_description_for_rules_and_user_account)
    end

    it "should reject attribute that are too short" do
      short = "a" * 9
      hash = @attr.merge(:prize_long_description_for_rules_and_user_account => short)
      Prize.new(hash).should have(1).error_on(:prize_long_description_for_rules_and_user_account)
    end
  end

  describe "tests on prize's models validations for prize_detailed_webpage_url" do
    it { should validate_presence_of(:prize_detailed_webpage_url) }
    it { should_not allow_value(" ").for(:prize_detailed_webpage_url) }
    it { should_not allow_value("string but not url").for(:prize_detailed_webpage_url) }   
  end

  describe "tests on prize's models validations for prize_image_url" do
    it { should validate_presence_of(:prize_image_url) }
    it { should validate_uniqueness_of(:prize_image_url).case_insensitive }
    it { should_not allow_value(" ").for(:prize_image_url) }
    it { should_not allow_value("stringbutnoturl").for(:prize_image_url) }     
  end

  describe "tests on prize's models validations for prize_image_alt" do
    it { should validate_presence_of(:prize_image_alt) }
    it { should_not allow_value(" ").for(:prize_image_alt) }

    it "should reject attribute that are too long" do
      long = "a" * 31
      hash = @attr.merge(:prize_image_alt => long)
      Prize.new(hash).should have(1).error_on(:prize_image_alt)
    end
  end

  describe "tests on prize's models validations for prize_type" do
    it { should validate_presence_of(:prize_type) }
    it { should_not allow_value(" ").for(:prize_type) }
    it { should ensure_inclusion_of(:prize_type).in_array(PRIZE_TYPES) }
  end

  describe "tests on prize's models validations for prize_initial_stock_quantity" do
    it { should validate_presence_of(:prize_initial_stock_quantity) }
    it { should_not allow_value(" ").for(:prize_initial_stock_quantity) }

    it { should validate_numericality_of(:prize_initial_stock_quantity).only_integer }
    it { should validate_numericality_of(:prize_initial_stock_quantity).is_greater_than_or_equal_to(1) }
  end

  describe "tests on prize's models validations for prize_unit_certified_market_value" do
    it { should validate_presence_of(:prize_unit_certified_market_value) }
    it { should_not allow_value(" ").for(:prize_unit_certified_market_value) }

    it { should validate_numericality_of(:prize_unit_certified_market_value).only_integer }
    it { should validate_numericality_of(:prize_unit_certified_market_value).is_greater_than_or_equal_to(1) }
    it { should validate_numericality_of(:prize_unit_certified_market_value).is_less_than_or_equal_to(1000000) }
  end

  describe "tests on prize's models validations for prize_date_for_certified_market_value" do
    it { should validate_presence_of(:prize_date_for_certified_market_value) }
    it { should_not allow_value(Time.zone.today - 1).for(:prize_date_for_certified_market_value).on(:create) } # has to be at least today
  end

  describe "tests on prize's models validations for prize_require_additional_user_info" do
    it { should validate_presence_of(:prize_require_additional_user_info) }
    it { should ensure_inclusion_of(:prize_require_additional_user_info).in_array(%w(true false)) }
  end

  describe "tests on prize's models validations for prize_max_nb_days_for_claiming" do
    it { should validate_presence_of(:prize_max_nb_days_for_claiming) }
    it { should_not allow_value(" ").for(:prize_max_nb_days_for_claiming) }

    it { should validate_numericality_of(:prize_max_nb_days_for_claiming).only_integer }
    it { should validate_numericality_of(:prize_max_nb_days_for_claiming).is_greater_than_or_equal_to(7) }
    it { should validate_numericality_of(:prize_max_nb_days_for_claiming).is_less_than_or_equal_to(90) }
  end

  describe "tests on prize's models validations for prize_expiry_date" do
    it { should_not allow_value(Time.zone.today - 1).for(:prize_expiry_date).on(:create) } # has to be at least today
  end

  describe "tests on prize's models validations for prize_category" do
    it { should validate_presence_of(:prize_category) }
    it { should_not allow_value(" ").for(:prize_category) }
    it { should ensure_inclusion_of(:prize_category).in_array(PRIZE_CATEGORIES) }
  end

  describe "tests on prize's models validations for prize_sourcer_company_name" do

    it "should reject attribute that are too long" do
      long = "a" * 101
      hash = @attr.merge(:prize_sourcer_company_name => long)
      Prize.new(hash).should have(1).error_on(:prize_sourcer_company_name)
    end

    it "should reject attribute that are too short" do
      short = "a" * 2
      hash = @attr.merge(:prize_sourcer_company_name => short)
      Prize.new(hash).should have(1).error_on(:prize_sourcer_company_name)
    end
  end

  describe "tests on prize's models validations for prize_sourcer_contact_point_name" do

    it { should validate_presence_of(:prize_sourcer_contact_point_name) }
    it { should_not allow_value(" ").for(:prize_sourcer_contact_point_name)}

    it "should reject attribute that are too long" do
      long = "a" * 101
      hash = @attr.merge(:prize_sourcer_contact_point_name => long)
      Prize.new(hash).should have(1).error_on(:prize_sourcer_contact_point_name)
    end

    it "should reject attribute that are too short" do
      short = "a" * 2
      hash = @attr.merge(:prize_sourcer_contact_point_name => short)
      Prize.new(hash).should have(1).error_on(:prize_sourcer_contact_point_name)
    end
  end

  describe "tests on prize's models validations for prize_sourcer_contact_point_direct_phone" do

    context "if prize_sourcer_contact_point_name present" do # test when sourcer is present
      before { subject.stub(:prize_sourcer_company_name?) { true } }
      it { should validate_presence_of(:prize_sourcer_contact_point_direct_phone) }
      it { should_not allow_value(" ").for(:prize_sourcer_contact_point_direct_phone) }
    end 

    context "if prize_sourcer_contact_point_name not present" do # test when sourcer is not present
      before { subject.stub(:prize_sourcer_company_name?) { false } }
      it { should_not validate_presence_of(:prize_sourcer_contact_point_direct_phone) }
    end 

    it "should reject attribute that are too long" do
      long = "a" * 21
      hash = @attr.merge(:prize_sourcer_contact_point_direct_phone => long)
      Prize.new(hash).should have(1).error_on(:prize_sourcer_contact_point_direct_phone)
    end

    it "should reject attribute that are too short" do
      short = "a" * 3
      hash = @attr.merge(:prize_sourcer_contact_point_direct_phone => short)
      Prize.new(hash).should have(1).error_on(:prize_sourcer_contact_point_direct_phone)
    end
  end

  describe "tests on prize's models validations for prize_sourcer_contact_point_email" do

    context "if prize_sourcer_contact_point_name present" do # test when sourcer is present
      before { subject.stub(:prize_sourcer_company_name?) { true } }
      it { should validate_presence_of(:prize_sourcer_contact_point_email) }
      it { should_not allow_value(" ").for(:prize_sourcer_contact_point_email) }
      it { should_not allow_value("blah").for(:prize_sourcer_contact_point_email) } # need to include format with @
    end 

    context "if prize_sourcer_contact_point_name not present" do # test when sourcer is not present
      before { subject.stub(:prize_sourcer_company_name?) { false } }
      it { should_not validate_presence_of(:prize_sourcer_contact_point_email)  }
    end 

    it "should reject attribute that are too long" do
      long = "a@" * 51
      hash = @attr.merge(:prize_sourcer_contact_point_email => long)
      Prize.new(hash).should have(1).error_on(:prize_sourcer_contact_point_email)
    end

  end

  describe "tests on prize's models validations for prize_sourcer_how_to_contact_details" do

    context "if prize_sourcer_contact_point_name present" do # test when sourcer is present
      before { subject.stub(:prize_sourcer_company_name?) { true } }
      it { should validate_presence_of(:prize_sourcer_how_to_contact_details) }
      it { should_not allow_value(" ").for(:prize_sourcer_how_to_contact_details) }
    end 

    context "if prize_sourcer_contact_point_name not present" do # test when sourcer is not present
      before { subject.stub(:prize_sourcer_company_name?) { false } }
      it { should_not validate_presence_of(:prize_sourcer_how_to_contact_details)  }
    end 

    it "should reject attribute that are too long" do
      long = "a" * 501
      hash = @attr.merge(:prize_sourcer_how_to_contact_details => long)
      Prize.new(hash).should have(1).error_on(:prize_sourcer_how_to_contact_details)
    end

    it "should reject attribute that are too short" do
      short = "a" * 3
      hash = @attr.merge(:prize_sourcer_how_to_contact_details => short)
      Prize.new(hash).should have(1).error_on(:prize_sourcer_how_to_contact_details)
    end
  end

  describe "tests on prize's models validations for prize_sourcer_crm_profile_url" do

    context "if sourcer present" do # test when sourcer is present
      before { subject.stub(:prize_sourcer_company_name?) { true } }
      it { should validate_presence_of(:prize_sourcer_crm_profile_url) }
      it { should_not allow_value(" ").for(:prize_sourcer_crm_profile_url) }
      it { should_not allow_value("stringbuturl").for(:prize_sourcer_crm_profile_url) }
    end 

    context "if sourcer not present" do # test when sourcer is not present
      before { subject.stub(:prize_sourcer_company_name?) { false } }
      it { should_not validate_presence_of(:prize_sourcer_crm_profile_url) }
    end 
  end

  describe "tests on prize's models validations for prize_fully_stocked_validated" do
    # it { should validate_presence_of(:prize_fully_stocked_validated) }
    # it { should ensure_inclusion_of(:prize_fully_stocked_validated).in_array(%w(true false)) }
  end

  describe "tests on prize's models validations for admin_user_id" do
     it { should validate_presence_of(:admin_user_id) }
     it { should_not allow_mass_assignment_of(:admin_user_id) }
     it { should allow_mass_assignment_of(:admin_user_id).as(:admin_user) }
     it { should validate_numericality_of(:admin_user_id) }
  end  

  describe "tests on prize's models validations for deal_id" do
     it { should validate_presence_of(:deal_id) }
     it { should_not allow_mass_assignment_of(:deal_id) }
     it { should allow_mass_assignment_of(:deal_id).as(:admin_user) }
     it { should validate_numericality_of(:deal_id) }
  end 

end

I have adjusted Garbage collector( http://makandracards.com/makandra/950-speed-up-rspec-by-deferring-garbage-collection ) but it almost had no effect. 我已经调整了垃圾收集器( http://makandracards.com/makandra/950-speed-up-rspec-by-deferring-garbage-collection ),但几乎没有效果。

class DeferredGarbageCollection

  DEFERRED_GC_THRESHOLD = (ENV['DEFER_GC'] || 10.0).to_f

  @@last_gc_run = Time.now

  def self.start
    GC.disable if DEFERRED_GC_THRESHOLD > 0
  end

  def self.reconsider
    if DEFERRED_GC_THRESHOLD > 0 && Time.now - @@last_gc_run >= DEFERRED_GC_THRESHOLD
      GC.enable
      GC.start
      GC.disable
      @@last_gc_run = Time.now
    end
  end
end

I use https://github.com/tmm1/perftools.rb to assess the time spent and understand why it takes so long. 我使用https://github.com/tmm1/perftools.rb来评估花费的时间并了解为什么要花费这么长时间。 Here is the analysis by perftools 这是perftools的分析

Total: 533 samples
      45   8.4%   8.4%       45   8.4% garbage_collector
      38   7.1%  15.6%       40   7.5% String#gsub
      35   6.6%  22.1%       35   6.6% String#=~
      20   3.8%  25.9%       20   3.8% Hash#initialize_copy
      15   2.8%  28.7%       29   5.4% Enumerable#inject
      14   2.6%  31.3%      201  37.7% I18n::Backend::Base#translate
      13   2.4%  33.8%      203  38.1% Kernel#catch
      13   2.4%  36.2%       18   3.4% URI::Parser#make_regexp
      12   2.3%  38.5%       12   2.3% PG::Connection#async_exec
      10   1.9%  40.3%      483  90.6% Array#map
       9   1.7%  42.0%       18   3.4% ActiveRecord::DynamicMatchers#respond_to?
       9   1.7%  43.7%        9   1.7% Hash#has_key?
       9   1.7%  45.4%        9   1.7% String#gsub!
       7   1.3%  46.7%        7   1.3% Class#logger
       7   1.3%  48.0%        7   1.3% Regexp#match
       6   1.1%  49.2%       12   2.3% #<Module:0x00000002cbf5a0>#normalize_key
       6   1.1%  50.3%       64  12.0% ActiveModel::Translation#human_attribute_name
       6   1.1%  51.4%        6   1.1% Kernel#is_a?
       6   1.1%  52.5%        7   1.3% Kernel.Float
       6   1.1%  53.7%        6   1.1% Regexp#===
       5   0.9%  54.6%      209  39.2% #<Module:0x00000002cbf5a0>#translate
       5   0.9%  55.5%      282  52.9% ActiveModel::Errors#generate_message
       5   0.9%  56.5%        5   0.9% Array#concat
       5   0.9%  57.4%       47   8.8% Hash#each
       5   0.9%  58.3%        5   0.9% I18n::Config#backend
       5   0.9%  59.3%       18   3.4% Kernel#dup
       5   0.9%  60.2%       10   1.9% MonitorMixin#mon_synchronize
       4   0.8%  61.0%        6   1.1% #<Module:0x00000002cbf5a0>#config
       4   0.8%  61.7%       24   4.5% #<Module:0x00000002cbf5a0>#normalize_keys
       4   0.8%  62.5%        4   0.8% ActiveRecord::Translation#lookup_ancestors
       4   0.8%  63.2%        4   0.8% Hash#delete
       4   0.8%  64.0%        6   1.1% Hash#except!
       4   0.8%  64.7%        4   0.8% Hash#values_at
       4   0.8%  65.5%       51   9.6% I18n::Backend::Simple::Implementation#lookup
       4   0.8%  66.2%        4   0.8% Kernel#require
       4   0.8%  67.0%        4   0.8% Kernel#respond_to?
       4   0.8%  67.7%        4   0.8% String#intern
       3   0.6%  68.3%        3   0.6% #<Module:0x00000002cbf5a0>#normalized_key_cache
       3   0.6%  68.9%        6   1.1% #<Module:0x007f8a0cd5fdc0>#__temp__
       3   0.6%  69.4%       10   1.9% ActiveRecord::ConnectionAdapters::PostgreSQLAdapter#extract_pg_identifier_from_name
       3   0.6%  70.0%       42   7.9% ActiveSupport::LogSubscriber#call
       3   0.6%  70.5%        3   0.6% Array#-
       3   0.6%  71.1%        9   1.7% Hash#merge
       3   0.6%  71.7%      123  23.1% I18n::Backend::Base#default
       3   0.6%  72.2%        8   1.5% I18n::MissingTranslation::Base#initialize
       3   0.6%  72.8%        3   0.6% IO#write
       3   0.6%  73.4%        3   0.6% Kernel#throw
       3   0.6%  73.9%      480  90.1% RSpec::Core::Example#run
       3   0.6%  74.5%        3   0.6% Regexp#initialize
       3   0.6%  75.0%        3   0.6% String#%
       3   0.6%  75.6%        7   1.3% Time#minus_with_coercion
       2   0.4%  76.0%       22   4.1% ActiveModel::Validations::UrlValidator#validate_each
       2   0.4%  76.4%       20   3.8% ActiveRecord::LogSubscriber#sql
       2   0.4%  76.7%        3   0.6% ActiveSupport::LogSubscriber#color
       2   0.4%  77.1%        2   0.4% ActiveSupport::Notifications::Fanout#listeners_for
       2   0.4%  77.5%        4   0.8% Arel::Visitors::Visitor#visit
       2   0.4%  77.9%       10   1.9% Array#collect
       2   0.4%  78.2%        2   0.4% Array#flatten!
       2   0.4%  78.6%        2   0.4% Array#hash
       2   0.4%  79.0%        2   0.4% Class#configurations
       2   0.4%  79.4%        7   1.3% Class#match
       2   0.4%  79.7%       17   3.2% Hash#except
       2   0.4%  80.1%        2   0.4% Logger::SimpleFormatter#call
       2   0.4%  80.5%        2   0.4% Marshal.dump_without_mocks
       2   0.4%  80.9%       63  11.8% Module#interpolate
       2   0.4%  81.2%      361  67.7% Prize#_run__2501234485523728663__validate__1858047214644115366__callbacks
       2   0.4%  81.6%        2   0.4% Symbol#to_s
       2   0.4%  82.0%        2   0.4% Thread#[]
       2   0.4%  82.4%        2   0.4% Time#initialize
       1   0.2%  82.6%        2   0.4% #<Module:0x00000002cbf5a0>#handle_exception
       1   0.2%  82.7%        1   0.2% ActiveModel::Errors#[]
       1   0.2%  82.9%      280  52.5% ActiveModel::Errors#add
       1   0.2%  83.1%      278  52.2% ActiveModel::Errors#normalize_message
       1   0.2%  83.3%       67  12.6% ActiveModel::Name#human
       1   0.2%  83.5%      364  68.3% ActiveModel::Validations::Callbacks#run_validations!
       1   0.2%  83.7%        8   1.5% ActiveModel::Validations::NumericalityValidator#parse_raw_value_as_a_number
       1   0.2%  83.9%      149  28.0% ActiveModel::Validations::PresenceValidator#validate
       1   0.2%  84.1%        4   0.8% ActiveRecord::Associations::JoinDependency#initialize
       1   0.2%  84.2%        5   0.9% ActiveRecord::AttributeMethods#respond_to?
       1   0.2%  84.4%        1   0.2% ActiveRecord::AttributeMethods::BeforeTypeCast#read_attribute_before_type_cast
       1   0.2%  84.6%        4   0.8% ActiveRecord::AttributeMethods::Dirty#write_attribute
       1   0.2%  84.8%        1   0.2% ActiveRecord::AttributeMethods::Write#type_cast_attribute_for_write
       1   0.2%  85.0%       62  11.6% ActiveRecord::ConnectionAdapters::AbstractAdapter#log
       1   0.2%  85.2%       69  12.9% ActiveRecord::ConnectionAdapters::PostgreSQLAdapter#disable_referential_integrity
       1   0.2%  85.4%        1   0.2% ActiveRecord::ConnectionAdapters::PostgreSQLAdapter#quote
       1   0.2%  85.6%        1   0.2% ActiveRecord::ConnectionAdapters::PostgreSQLColumn#type_cast_with_extended_types
       1   0.2%  85.7%        1   0.2% ActiveRecord::ExplainSubscriber#call
       1   0.2%  85.9%        1   0.2% ActiveRecord::QueryMethods#where
       1   0.2%  86.1%        1   0.2% ActiveRecord::Result#hash_rows
       1   0.2%  86.3%        1   0.2% ActiveRecord::Scoping::ClassMethods#current_scope=
       1   0.2%  86.5%        5   0.9% ActiveRecord::SpawnMethods#except
       1   0.2%  86.7%       30   5.6% 

The whole file is here if necessary: https://docs.google.com/document/d/16F38guxjBVFpu8Xp1rwK14TWREPcM3wtiLvfBGG7NB0/edit?usp=sharing 如果需要,整个文件位于此处: https : //docs.google.com/document/d/16F38guxjBVFpu8Xp1rwK14TWREPcM3wtiLvfBGG7NB0/edit?usp=sharing

I read a few articles on how to improve time, but I would like first to understand why it is so slow (30 minutes!) and then I could pick the right test optimization techniques. 我读了几篇有关如何缩短时间的文章,但是我想首先了解为什么它这么慢(30分钟!),然后才可以选择正确的测试优化技术。

It seems like it's using most of the time generating the error messages for your validations. 似乎大多数时候都在使用错误消息进行验证。 You could try to optimize that, but if what you're looking for is a simple speedup, you can just stub that whole part of the process. 您可以尝试对其进行优化,但是如果您要查找的是简单的加速,则可以将过程的整个部分都保留下来。 I would just stub ActiveModel::Errors#generate_message with "error message" , which should save a lot of processing time. 我只是将ActiveModel::Errors#generate_message"error message"一起存根,这样可以节省很多处理时间。

ActiveModel::Errors.any_instance.stub(:generate_message).and_return('error message')

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM