2012-06-27 91 views
3

我正在rails中創建一個REST API。我正在使用RSpec。我想盡量減少數據庫調用的次數,所以我想添加一個自動測試來驗證作爲特定操作的一部分而正在執行的數據庫調用的數量。 是否有一種簡單的方法將其添加到我的測試中? 我正在尋找的是一種方法來監視/記錄由於單個API調用而對數據庫進行的調用。 如果這不能用RSpec完成,但可以用其他測試工具完成,那也很棒。如何測試Rails中的數據庫調用次數

回答

2

最容易的事情中的Rails 3可能是鉤到通知API。

該用戶

class SqlCounter< ActiveSupport::LogSubscriber 

    def self.count= value 
    Thread.current['query_count'] = value 
    end 

    def self.count 
    Thread.current['query_count'] || 0 
    end 

    def self.reset_count 
    result, self.count = self.count, 0 
    result 
    end 

    def sql(event) 
    self.class.count += 1 
    puts "logged #{event.payload[:sql]}" 
    end 
end 

SqlCounter.attach_to :active_record 

將打印每一個執行的SQL語句到控制檯和計數。然後,您可以編寫規範,如

expect do 
    # do stuff 
end.to change(SqlCounter, :count).by(2) 

您可能需要過濾掉一些語句,比如那些開始/提交事務或那些活動記錄發出來確定表的結構。

0

Fredrick的回答對我很好,但在我的情況下,我也想知道每個ActiveRecord類的調用個數。我做了一些修改,並以此爲結束,以防其他人使用。

class SqlCounter< ActiveSupport::LogSubscriber 

    # Returns the number of database "Loads" for a given ActiveRecord class. 
    def self.count(clazz) 
    name = clazz.name + ' Load' 
    Thread.current['log'] ||= {} 
    Thread.current['log'][name] || 0 
    end 

    # Returns a list of ActiveRecord classes that were counted. 
    def self.counted_classes 
    log = Thread.current['log'] 
    loads = log.keys.select {|key| key =~ /Load$/ } 
    loads.map { |key| Object.const_get(key.split.first) } 
    end 

    def self.reset_count 
    Thread.current['log'] = {} 
    end 

    def sql(event) 
    name = event.payload[:name] 
    Thread.current['log'] ||= {} 
    Thread.current['log'][name] ||= 0 
    Thread.current['log'][name] += 1 
    end 
end 

SqlCounter.attach_to :active_record 

expect do 
    # do stuff 
end.to change(SqlCounter, :count).by(2)