23

Rspecの例と並行してResqueを実装しているときに、混乱しました。以下は、高価なメソッド.generate(self) クラスSomeClass ... ChangeGenerator.generate(self)...endを持つクラスです。

resqueを実装した後、上記のクラスを次のように変更し、ChangeRecorderJobクラスを追加しました。

class SomeClass
  ...
  Resque.enqueue(ChangeRecorderJob, self.id)
  ...
end

class ChangeRecorderJob
  @queue = :change_recorder_job

  def self.perform(noti_id)
    notification = Notification.find(noti_id)    
    ChangeGenerator.generate(notification)
  end
end

それは完璧に動作します。しかし、私には2つの懸念があります。

以前、私のサンプル仕様は、.generate(self)メソッドのスタック全体をテストするために使用されていました。しかし、これをResqueの仕事に取り入れたので、例をブリッジして、分離せずに同じテストをグリーンにする方法を教えてください。または、テストを分離する必要がありますか?

最後に、エンキューするジョブが10個ある場合、メソッドを使用して10個の個別のジョブクラスを作成する必要がありますself.performか?

4

3 に答える 3

34

このような非同期のものをテストすることは常に注意が必要です。私たちがしていることは:

  • 機能テストでは、ジョブがキューに入れられることを確認します。通常は、モカなどを期待して使用するだけで十分です。テストRedisサーバーを実行する場合は、正しいキューが拡張され、ジョブパラメーターが正しいことを確認できます。その時点でResque自体を少しテストしていますが。

  • ジョブは、単体テストとして個別にテストされます。と呼ばれるクラスメソッドがあるだけなので、perform単体テストは非常に簡単です。あなたの場合、ChangeRecorderJob.performがあなたが望むことをすることをテストするでしょう。私たちは、ジョブが適切なキューにあること、ジョブのパラメーターが有効であること、およびジョブが必要なことを実行することをテストする傾向があります。

  • さて、すべてを一緒にテストするのは難しい部分です。私はこれを2つの異なる方法で行いましたが、それぞれに長所と短所があります。

    • ジョブを同期的に実行するためのMonkey-patchResqueue.enqueueresque 1.14.0以降 、monkey-patchingの代わりに初期化子で使用できます。Resque.inline = true
    • キューからジョブをポップし、実際にフォークされたプロセスで実行するワーカーをシミュレートします

ジョブを同期的に実行することは、2つのうちではるかに簡単です。spec_helperに次のようなものをロードするだけです。

モジュールResque
  alias_method:enqueue_async、:enqueue

  def self.enqueue(klass、* args)
    klass.new(0、* args).perform
  終わり
終わり

Resque.inline = trueresque 1.14.0以降では、モンキーパッチの代わりにイニシャライザーで設定できます。古いバージョンのresqueで立ち往生している場合は、モンキーパッチが必要です。

ここでは同期して実行しているため、長時間実行するジョブのコストが発生することに注意してください。おそらくもっと重要なのは、同じプロセスで実行されるため、ジョブの実行方法を完全に正確に表したものではないということです。

resqueのように、フォークされたワーカーでジョブを実行するには、次のようなことを行う必要があります。

def run_resque_job(job_class、job_args、opts = {})
  queue = opts [:queue] || 「test_queue」

  Resque :: Job.create(queue、job_class、* job_args)
  ワーカー=Resque:: Worker.new(queue)
  worker.very_verbose = opts [:verbose]の場合はtrue

  opts [:fork]の場合
    #単一のジョブを実行してからシャットダウン
    defworker.done_working
      素晴らしい
      シャットダウン
    終わり
    worker.work(0.01)
  そうしないと
    job = worker.reserve
    worker.perform(job)
  終わり
終わり

ワーカーがジョブをキューからポップするのにわずかな遅延があります。そして当然、ワーカーがポップオフするキューを持つように、テストredisサーバーを実行する必要があります。

他の人がresqueジョブをテストする賢い方法を思いついたと確信しています。これらは私のために働いているものです。

于 2011-03-04T13:41:18.927 に答える
8

ユニットテストにはresque_specを使用します。

describe "#recalculate" do
  before do
    ResqueSpec.reset!
  end

  it "adds person.calculate to the Person queue" do
    person.recalculate
    Person.should have_queued(person.id, :calculate).in(:people)
  end
end

そして、統合テストの場合:

describe "#score!" do
  before do
    ResqueSpec.reset!
  end

  it "increases the score" do
    with_resque do
      game.score!
    end
    game.score.should == 10
  end
end
于 2011-06-09T16:05:20.757 に答える
1

2 つの異なるテストを行う必要があります。1 つはエンキュー用で、ジョブが Resque キューにエンキューされていることを確認するためのもので、もう 1 つは、ワーカーによってピックアップされたときにキュー内のジョブが要件に従って実行されていることを確認するためのものです。

いいえ、10 個の異なる perform メソッドを記述する必要はありません。Resque ワーカーを実行すると、キューからジョブが取得され、ジョブの .perform メソッドがやみくもに呼び出されます。したがって、ジョブには perform メソッドが必要です。

于 2011-03-04T15:29:32.947 に答える