3

RailsでREST APIを作成しています。私は RSpec を使用しています。データベース呼び出しの数を最小限に抑えたいので、特定のアクションの一部として実行されるデータベース呼び出しの数を検証する自動テストを追加したいと考えています。それを私のテストに追加する簡単な方法はありますか? 私が探しているのは、単一の API 呼び出しの結果としてデータベースに対して行われている呼び出しを監視/記録する方法です。これが RSpec では実行できなくても、他のテスト ツールで実行できる場合、それも素晴らしいことです。

4

4 に答える 4

3

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)

テーブルの構造を決定するために、トランザクションを開始/コミットするステートメントや、アクティブ レコードが発行するステートメントなど、いくつかのステートメントを除外したい場合があります。

于 2012-06-29T21:05:54.910 に答える
1

Explainの使用に興味があるかもしれません。しかし、それは自動ではありません。各アクションを手動で分析する必要があります。しかし、重要なのは db 呼び出しの数ではなく、その性質であるため、これは良いことかもしれません。例: インデックスを使用していますか?

これをチェックして:

http://weblog.rubyonrails.org/2011/12/6/what-s-new-in-edge-rails-explain/

于 2012-06-29T20:38:54.640 に答える
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)
于 2014-10-06T23:49:51.667 に答える