2014-01-11 95 views
1

我在我的Rails應用程序中進行了一個簡單的測試,它的測試持續時間比其他類似的測試要長得多。Rails Test ::模型驗證的單元測試出奇的慢 - I18n?

它需要的實時1至2秒,以如下運行test_invalid_without_name

VALID_PARAMS = { name: 'Client record' } 

def test_invalid_without_name 
    c = Client.new(VALID_PARAMS) 
    c.name = nil 
    refute c.valid?, 'should not be valid without a name' 
end 

下一個測試,test_valid_with_all_params需要不到1/1/100秒的:

def test_valid_with_all_params 
    c = Client.new(VALID_PARAMS) 
    assert c.valid?, 'should be valid with appropriate parameters' 
end 

客戶模型在這個階段是完全直截了當的:

class Client < ActiveRecord::Base 

    belongs_to :entity, polymorphic: true 

    validates :name, presence: true 

end 

Can anyon要麼發現這裏出了什麼問題,要麼給我一個想法,我應該看看下一個試圖弄清楚的地方?

更新1

我已經使用ruby-prof來分析代碼,似乎很多的時間被消耗在Psych寶石。我相信這是ActiveRecord::..#serialize使用,這是我如下正在使用另一種模式:

class Opportunity < ActiveRecord::Base 
    belongs_to :client 
    serialize :details, Hash 
end 

但是,刪除調用serialize這裏不會對客戶端測試有什麼區別(我看不到爲什麼會這樣,這兩個類是關聯的,但沒有機會在客戶端測試中實例化)。

更新2

原來的I18n,因爲使用它精極度緊張被調用。我在這一點上的假設是,失敗的驗證會導致I18n轉到語言環境文件以提取錯誤消息。我會研究I18n的測試...

回答

2

事實證明,解決這個問題的合適方法是使用ruby-prof如下。在通話

gem 'ruby-prof' 

裹測試代碼分析器:

加入Gemfile中(該development組)

def test_invalid_without_name 
    RubyProf.start 

    cr = Client.new(VALID_PARAMS) 
    cr.name = nil 
    refute cr.valid?, 'should not be valid without a name' 

    result = RubyProf.stop 
    printer = RubyProf::CallStackPrinter.new(result) 
    printer.print(File.open(File.join(Rails.root, 'profile_invalid_without_name.html'), 'w')) 
end 

這將在根目錄中創建一個交互式的HTML文檔您Rails應用程序,它顯示了花費在哪裏的細節。

在這種情況下,在I18n尋找翻譯時是80%+。添加以下行config/environments/test.rb存根它在測試:

I18n.backend = I18n::Backend::KeyValue.new({}) 

我可能會做出下面的其他改進未來:

  1. 更具體用在哪裏,踩滅的I18n,所以全堆棧驗收測試可以使用真實的東西。

  2. 編寫一個更方便的分析方法。它看起來像紅寶石教授提供了各種其他機制來激活它,這只是最初使用最簡單的方法。

1

沒有更多信息就無法回答這個問題。

  • 會出現這種情況,當你運行測試的每個獨立?
  • 你在setup/teardown或test_helper.rb中有任何東西嗎?
  • 如果您通過名稱=> nil而不是設置它的散列,它會發生嗎?
  • 您是否重新定義了名字制定者?
  • 你對模特有任何回調嗎?
+0

嗨,這裏有一些很好的建議,謝謝。我沒有重新定義setter或添加任何回調,也沒有setup/teardown:所有的代碼/測試代碼都在上面。正如你所建議的那樣,我現在已經試過逐一運行每個測試,慢速和快速測試的行爲都是一樣的。我也試着用'name:nil'設置一個散列,或者不把任何參數傳遞給'new',但是再次沒有時間差異。 – Leo