tr_resque 1.20.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. data/HISTORY.md +354 -0
  2. data/LICENSE +20 -0
  3. data/README.markdown +908 -0
  4. data/Rakefile +70 -0
  5. data/bin/resque +81 -0
  6. data/bin/resque-web +27 -0
  7. data/lib/resque.rb +369 -0
  8. data/lib/resque/errors.rb +10 -0
  9. data/lib/resque/failure.rb +96 -0
  10. data/lib/resque/failure/airbrake.rb +17 -0
  11. data/lib/resque/failure/base.rb +64 -0
  12. data/lib/resque/failure/hoptoad.rb +33 -0
  13. data/lib/resque/failure/multiple.rb +54 -0
  14. data/lib/resque/failure/redis.rb +51 -0
  15. data/lib/resque/failure/thoughtbot.rb +33 -0
  16. data/lib/resque/helpers.rb +94 -0
  17. data/lib/resque/job.rb +227 -0
  18. data/lib/resque/plugin.rb +66 -0
  19. data/lib/resque/server.rb +248 -0
  20. data/lib/resque/server/public/favicon.ico +0 -0
  21. data/lib/resque/server/public/idle.png +0 -0
  22. data/lib/resque/server/public/jquery-1.3.2.min.js +19 -0
  23. data/lib/resque/server/public/jquery.relatize_date.js +95 -0
  24. data/lib/resque/server/public/poll.png +0 -0
  25. data/lib/resque/server/public/ranger.js +73 -0
  26. data/lib/resque/server/public/reset.css +44 -0
  27. data/lib/resque/server/public/style.css +86 -0
  28. data/lib/resque/server/public/working.png +0 -0
  29. data/lib/resque/server/test_helper.rb +19 -0
  30. data/lib/resque/server/views/error.erb +1 -0
  31. data/lib/resque/server/views/failed.erb +67 -0
  32. data/lib/resque/server/views/key_sets.erb +19 -0
  33. data/lib/resque/server/views/key_string.erb +11 -0
  34. data/lib/resque/server/views/layout.erb +44 -0
  35. data/lib/resque/server/views/next_more.erb +10 -0
  36. data/lib/resque/server/views/overview.erb +4 -0
  37. data/lib/resque/server/views/queues.erb +49 -0
  38. data/lib/resque/server/views/stats.erb +62 -0
  39. data/lib/resque/server/views/workers.erb +109 -0
  40. data/lib/resque/server/views/working.erb +72 -0
  41. data/lib/resque/stat.rb +53 -0
  42. data/lib/resque/tasks.rb +61 -0
  43. data/lib/resque/version.rb +3 -0
  44. data/lib/resque/worker.rb +546 -0
  45. data/lib/tasks/redis.rake +161 -0
  46. data/lib/tasks/resque.rake +2 -0
  47. data/test/airbrake_test.rb +27 -0
  48. data/test/hoptoad_test.rb +26 -0
  49. data/test/job_hooks_test.rb +423 -0
  50. data/test/job_plugins_test.rb +230 -0
  51. data/test/plugin_test.rb +116 -0
  52. data/test/redis-test-cluster.conf +115 -0
  53. data/test/redis-test.conf +115 -0
  54. data/test/resque-web_test.rb +59 -0
  55. data/test/resque_test.rb +278 -0
  56. data/test/test_helper.rb +160 -0
  57. data/test/worker_test.rb +434 -0
  58. metadata +186 -0
@@ -0,0 +1,160 @@
1
+ require 'rubygems'
2
+
3
+ dir = File.dirname(File.expand_path(__FILE__))
4
+ $LOAD_PATH.unshift dir + '/../lib'
5
+ $TESTING = true
6
+ require 'test/unit'
7
+
8
+ require 'redis/namespace'
9
+ require 'resque'
10
+
11
+ begin
12
+ require 'leftright'
13
+ rescue LoadError
14
+ end
15
+
16
+
17
+ #
18
+ # make sure we can run redis
19
+ #
20
+
21
+ if !system("which redis-server")
22
+ puts '', "** can't find `redis-server` in your path"
23
+ puts "** try running `sudo rake install`"
24
+ abort ''
25
+ end
26
+
27
+
28
+ #
29
+ # start our own redis when the tests start,
30
+ # kill it when they end
31
+ #
32
+
33
+ at_exit do
34
+ next if $!
35
+
36
+ if defined?(MiniTest)
37
+ exit_code = MiniTest::Unit.new.run(ARGV)
38
+ else
39
+ exit_code = Test::Unit::AutoRunner.run
40
+ end
41
+
42
+ processes = `ps -A -o pid,command | grep [r]edis-test`.split("\n")
43
+ pids = processes.map { |process| process.split(" ")[0] }
44
+ puts "Killing test redis server..."
45
+ `rm -f #{dir}/dump.rdb #{dir}/dump-cluster.rdb`
46
+ pids.each { |pid| Process.kill("KILL", pid.to_i) }
47
+ exit exit_code
48
+ end
49
+
50
+ if ENV.key? 'RESQUE_DISTRIBUTED'
51
+ require 'redis/distributed'
52
+ puts "Starting redis for testing at localhost:9736 and localhost:9737..."
53
+ `redis-server #{dir}/redis-test.conf`
54
+ `redis-server #{dir}/redis-test-cluster.conf`
55
+ r = Redis::Distributed.new(['redis://localhost:9736', 'redis://localhost:9737'])
56
+ Resque.redis = Redis::Namespace.new :resque, :redis => r
57
+ else
58
+ puts "Starting redis for testing at localhost:9736..."
59
+ `redis-server #{dir}/redis-test.conf`
60
+ Resque.redis = 'localhost:9736'
61
+ end
62
+
63
+
64
+ ##
65
+ # test/spec/mini 3
66
+ # http://gist.github.com/25455
67
+ # chris@ozmm.org
68
+ #
69
+ def context(*args, &block)
70
+ return super unless (name = args.first) && block
71
+ require 'test/unit'
72
+ klass = Class.new(defined?(ActiveSupport::TestCase) ? ActiveSupport::TestCase : Test::Unit::TestCase) do
73
+ def self.test(name, &block)
74
+ define_method("test_#{name.gsub(/\W/,'_')}", &block) if block
75
+ end
76
+ def self.xtest(*args) end
77
+ def self.setup(&block) define_method(:setup, &block) end
78
+ def self.teardown(&block) define_method(:teardown, &block) end
79
+ end
80
+ (class << klass; self end).send(:define_method, :name) { name.gsub(/\W/,'_') }
81
+ klass.class_eval &block
82
+ # XXX: In 1.8.x, not all tests will run unless anonymous classes are kept in scope.
83
+ ($test_classes ||= []) << klass
84
+ end
85
+
86
+ ##
87
+ # Helper to perform job classes
88
+ #
89
+ module PerformJob
90
+ def perform_job(klass, *args)
91
+ resque_job = Resque::Job.new(:testqueue, 'class' => klass, 'args' => args)
92
+ resque_job.perform
93
+ end
94
+ end
95
+
96
+ #
97
+ # fixture classes
98
+ #
99
+
100
+ class SomeJob
101
+ def self.perform(repo_id, path)
102
+ end
103
+ end
104
+
105
+ class SomeIvarJob < SomeJob
106
+ @queue = :ivar
107
+ end
108
+
109
+ class SomeMethodJob < SomeJob
110
+ def self.queue
111
+ :method
112
+ end
113
+ end
114
+
115
+ class BadJob
116
+ def self.perform
117
+ raise "Bad job!"
118
+ end
119
+ end
120
+
121
+ class GoodJob
122
+ def self.perform(name)
123
+ "Good job, #{name}"
124
+ end
125
+ end
126
+
127
+ class BadJobWithSyntaxError
128
+ def self.perform
129
+ raise SyntaxError, "Extra Bad job!"
130
+ end
131
+ end
132
+
133
+ class BadFailureBackend < Resque::Failure::Base
134
+ def save
135
+ raise Exception.new("Failure backend error")
136
+ end
137
+ end
138
+
139
+ def with_failure_backend(failure_backend, &block)
140
+ previous_backend = Resque::Failure.backend
141
+ Resque::Failure.backend = failure_backend
142
+ yield block
143
+ ensure
144
+ Resque::Failure.backend = previous_backend
145
+ end
146
+
147
+ class Time
148
+ # Thanks, Timecop
149
+ class << self
150
+ attr_accessor :fake_time
151
+
152
+ alias_method :now_without_mock_time, :now
153
+
154
+ def now
155
+ fake_time || now_without_mock_time
156
+ end
157
+ end
158
+
159
+ self.fake_time = nil
160
+ end
@@ -0,0 +1,434 @@
1
+ require 'test_helper'
2
+
3
+ context "Resque::Worker" do
4
+ setup do
5
+ Resque.redis.flushall
6
+
7
+ Resque.before_first_fork = nil
8
+ Resque.before_fork = nil
9
+ Resque.after_fork = nil
10
+
11
+ @worker = Resque::Worker.new(:jobs)
12
+ Resque::Job.create(:jobs, SomeJob, 20, '/tmp')
13
+ end
14
+
15
+ test "can fail jobs" do
16
+ Resque::Job.create(:jobs, BadJob)
17
+ @worker.work(0)
18
+ assert_equal 1, Resque::Failure.count
19
+ end
20
+
21
+ test "failed jobs report exception and message" do
22
+ Resque::Job.create(:jobs, BadJobWithSyntaxError)
23
+ @worker.work(0)
24
+ assert_equal('SyntaxError', Resque::Failure.all['exception'])
25
+ assert_equal('Extra Bad job!', Resque::Failure.all['error'])
26
+ end
27
+
28
+ test "does not allow exceptions from failure backend to escape" do
29
+ job = Resque::Job.new(:jobs, {})
30
+ with_failure_backend BadFailureBackend do
31
+ @worker.perform job
32
+ end
33
+ end
34
+
35
+ test "fails uncompleted jobs on exit" do
36
+ job = Resque::Job.new(:jobs, {'class' => 'GoodJob', 'args' => "blah"})
37
+ @worker.working_on(job)
38
+ @worker.unregister_worker
39
+ assert_equal 1, Resque::Failure.count
40
+ end
41
+
42
+ class ::SimpleJobWithFailureHandling
43
+ def self.on_failure_record_failure(exception, *job_args)
44
+ @@exception = exception
45
+ end
46
+
47
+ def self.exception
48
+ @@exception
49
+ end
50
+ end
51
+
52
+ test "fails uncompleted jobs on exit, and calls failure hook" do
53
+ job = Resque::Job.new(:jobs, {'class' => 'SimpleJobWithFailureHandling', 'args' => ""})
54
+ @worker.working_on(job)
55
+ @worker.unregister_worker
56
+ assert_equal 1, Resque::Failure.count
57
+ assert(SimpleJobWithFailureHandling.exception.kind_of?(Resque::DirtyExit))
58
+ end
59
+
60
+ class ::SimpleFailingJob
61
+ @@exception_count = 0
62
+
63
+ def self.on_failure_record_failure(exception, *job_args)
64
+ @@exception_count += 1
65
+ end
66
+
67
+ def self.exception_count
68
+ @@exception_count
69
+ end
70
+
71
+ def self.perform
72
+ raise Exception.new
73
+ end
74
+ end
75
+
76
+ test "only calls failure hook once on exception" do
77
+ job = Resque::Job.new(:jobs, {'class' => 'SimpleFailingJob', 'args' => ""})
78
+ @worker.perform(job)
79
+ assert_equal 1, Resque::Failure.count
80
+ assert_equal 1, SimpleFailingJob.exception_count
81
+ end
82
+
83
+ test "can peek at failed jobs" do
84
+ 10.times { Resque::Job.create(:jobs, BadJob) }
85
+ @worker.work(0)
86
+ assert_equal 10, Resque::Failure.count
87
+
88
+ assert_equal 10, Resque::Failure.all(0, 20).size
89
+ end
90
+
91
+ test "can clear failed jobs" do
92
+ Resque::Job.create(:jobs, BadJob)
93
+ @worker.work(0)
94
+ assert_equal 1, Resque::Failure.count
95
+ Resque::Failure.clear
96
+ assert_equal 0, Resque::Failure.count
97
+ end
98
+
99
+ test "catches exceptional jobs" do
100
+ Resque::Job.create(:jobs, BadJob)
101
+ Resque::Job.create(:jobs, BadJob)
102
+ @worker.process
103
+ @worker.process
104
+ @worker.process
105
+ assert_equal 2, Resque::Failure.count
106
+ end
107
+
108
+ test "strips whitespace from queue names" do
109
+ queues = "critical, high, low".split(',')
110
+ worker = Resque::Worker.new(*queues)
111
+ assert_equal %w( critical high low ), worker.queues
112
+ end
113
+
114
+ test "can work on multiple queues" do
115
+ Resque::Job.create(:high, GoodJob)
116
+ Resque::Job.create(:critical, GoodJob)
117
+
118
+ worker = Resque::Worker.new(:critical, :high)
119
+
120
+ worker.process
121
+ assert_equal 1, Resque.size(:high)
122
+ assert_equal 0, Resque.size(:critical)
123
+
124
+ worker.process
125
+ assert_equal 0, Resque.size(:high)
126
+ end
127
+
128
+ test "can work on all queues" do
129
+ Resque::Job.create(:high, GoodJob)
130
+ Resque::Job.create(:critical, GoodJob)
131
+ Resque::Job.create(:blahblah, GoodJob)
132
+
133
+ worker = Resque::Worker.new("*")
134
+
135
+ worker.work(0)
136
+ assert_equal 0, Resque.size(:high)
137
+ assert_equal 0, Resque.size(:critical)
138
+ assert_equal 0, Resque.size(:blahblah)
139
+ end
140
+
141
+ test "can work with wildcard at the end of the list" do
142
+ Resque::Job.create(:high, GoodJob)
143
+ Resque::Job.create(:critical, GoodJob)
144
+ Resque::Job.create(:blahblah, GoodJob)
145
+ Resque::Job.create(:beer, GoodJob)
146
+
147
+ worker = Resque::Worker.new(:critical, :high, "*")
148
+
149
+ worker.work(0)
150
+ assert_equal 0, Resque.size(:high)
151
+ assert_equal 0, Resque.size(:critical)
152
+ assert_equal 0, Resque.size(:blahblah)
153
+ assert_equal 0, Resque.size(:beer)
154
+ end
155
+
156
+ test "can work with wildcard at the middle of the list" do
157
+ Resque::Job.create(:high, GoodJob)
158
+ Resque::Job.create(:critical, GoodJob)
159
+ Resque::Job.create(:blahblah, GoodJob)
160
+ Resque::Job.create(:beer, GoodJob)
161
+
162
+ worker = Resque::Worker.new(:critical, "*", :high)
163
+
164
+ worker.work(0)
165
+ assert_equal 0, Resque.size(:high)
166
+ assert_equal 0, Resque.size(:critical)
167
+ assert_equal 0, Resque.size(:blahblah)
168
+ assert_equal 0, Resque.size(:beer)
169
+ end
170
+
171
+ test "processes * queues in alphabetical order" do
172
+ Resque::Job.create(:high, GoodJob)
173
+ Resque::Job.create(:critical, GoodJob)
174
+ Resque::Job.create(:blahblah, GoodJob)
175
+
176
+ worker = Resque::Worker.new("*")
177
+ processed_queues = []
178
+
179
+ worker.work(0) do |job|
180
+ processed_queues << job.queue
181
+ end
182
+
183
+ assert_equal %w( jobs high critical blahblah ).sort, processed_queues
184
+ end
185
+
186
+ test "has a unique id" do
187
+ assert_equal "#{`hostname`.chomp}:#{$$}:jobs", @worker.to_s
188
+ end
189
+
190
+ test "complains if no queues are given" do
191
+ assert_raise Resque::NoQueueError do
192
+ Resque::Worker.new
193
+ end
194
+ end
195
+
196
+ test "fails if a job class has no `perform` method" do
197
+ worker = Resque::Worker.new(:perform_less)
198
+ Resque::Job.create(:perform_less, Object)
199
+
200
+ assert_equal 0, Resque::Failure.count
201
+ worker.work(0)
202
+ assert_equal 1, Resque::Failure.count
203
+ end
204
+
205
+ test "inserts itself into the 'workers' list on startup" do
206
+ @worker.work(0) do
207
+ assert_equal @worker, Resque.workers[0]
208
+ end
209
+ end
210
+
211
+ test "removes itself from the 'workers' list on shutdown" do
212
+ @worker.work(0) do
213
+ assert_equal @worker, Resque.workers[0]
214
+ end
215
+
216
+ assert_equal [], Resque.workers
217
+ end
218
+
219
+ test "removes worker with stringified id" do
220
+ @worker.work(0) do
221
+ worker_id = Resque.workers[0].to_s
222
+ Resque.remove_worker(worker_id)
223
+ assert_equal [], Resque.workers
224
+ end
225
+ end
226
+
227
+ test "records what it is working on" do
228
+ @worker.work(0) do
229
+ task = @worker.job
230
+ assert_equal({"args"=>[20, "/tmp"], "class"=>"SomeJob"}, task['payload'])
231
+ assert task['run_at']
232
+ assert_equal 'jobs', task['queue']
233
+ end
234
+ end
235
+
236
+ test "clears its status when not working on anything" do
237
+ @worker.work(0)
238
+ assert_equal Hash.new, @worker.job
239
+ end
240
+
241
+ test "knows when it is working" do
242
+ @worker.work(0) do
243
+ assert @worker.working?
244
+ end
245
+ end
246
+
247
+ test "knows when it is idle" do
248
+ @worker.work(0)
249
+ assert @worker.idle?
250
+ end
251
+
252
+ test "knows who is working" do
253
+ @worker.work(0) do
254
+ assert_equal [@worker], Resque.working
255
+ end
256
+ end
257
+
258
+ test "keeps track of how many jobs it has processed" do
259
+ Resque::Job.create(:jobs, BadJob)
260
+ Resque::Job.create(:jobs, BadJob)
261
+
262
+ 3.times do
263
+ job = @worker.reserve
264
+ @worker.process job
265
+ end
266
+ assert_equal 3, @worker.processed
267
+ end
268
+
269
+ test "keeps track of how many failures it has seen" do
270
+ Resque::Job.create(:jobs, BadJob)
271
+ Resque::Job.create(:jobs, BadJob)
272
+
273
+ 3.times do
274
+ job = @worker.reserve
275
+ @worker.process job
276
+ end
277
+ assert_equal 2, @worker.failed
278
+ end
279
+
280
+ test "stats are erased when the worker goes away" do
281
+ @worker.work(0)
282
+ assert_equal 0, @worker.processed
283
+ assert_equal 0, @worker.failed
284
+ end
285
+
286
+ test "knows when it started" do
287
+ time = Time.now
288
+ @worker.work(0) do
289
+ assert_equal time.to_s, @worker.started.to_s
290
+ end
291
+ end
292
+
293
+ test "knows whether it exists or not" do
294
+ @worker.work(0) do
295
+ assert Resque::Worker.exists?(@worker)
296
+ assert !Resque::Worker.exists?('blah-blah')
297
+ end
298
+ end
299
+
300
+ test "sets $0 while working" do
301
+ @worker.work(0) do
302
+ ver = Resque::Version
303
+ assert_equal "resque-#{ver}: Processing jobs since #{Time.now.to_i}", $0
304
+ end
305
+ end
306
+
307
+ test "can be found" do
308
+ @worker.work(0) do
309
+ found = Resque::Worker.find(@worker.to_s)
310
+ assert_equal @worker.to_s, found.to_s
311
+ assert found.working?
312
+ assert_equal @worker.job, found.job
313
+ end
314
+ end
315
+
316
+ test "doesn't find fakes" do
317
+ @worker.work(0) do
318
+ found = Resque::Worker.find('blah-blah')
319
+ assert_equal nil, found
320
+ end
321
+ end
322
+
323
+ test "cleans up dead worker info on start (crash recovery)" do
324
+ # first we fake out two dead workers
325
+ workerA = Resque::Worker.new(:jobs)
326
+ workerA.instance_variable_set(:@to_s, "#{`hostname`.chomp}:1:jobs")
327
+ workerA.register_worker
328
+
329
+ workerB = Resque::Worker.new(:high, :low)
330
+ workerB.instance_variable_set(:@to_s, "#{`hostname`.chomp}:2:high,low")
331
+ workerB.register_worker
332
+
333
+ assert_equal 2, Resque.workers.size
334
+
335
+ # then we prune them
336
+ @worker.work(0) do
337
+ assert_equal 1, Resque.workers.size
338
+ end
339
+ end
340
+
341
+ test "worker_pids returns pids" do
342
+ known_workers = @worker.worker_pids
343
+ assert !known_workers.empty?
344
+ end
345
+
346
+ test "Processed jobs count" do
347
+ @worker.work(0)
348
+ assert_equal 1, Resque.info[:processed]
349
+ end
350
+
351
+ test "Will call a before_first_fork hook only once" do
352
+ Resque.redis.flushall
353
+ $BEFORE_FORK_CALLED = 0
354
+ Resque.before_first_fork = Proc.new { $BEFORE_FORK_CALLED += 1 }
355
+ workerA = Resque::Worker.new(:jobs)
356
+ Resque::Job.create(:jobs, SomeJob, 20, '/tmp')
357
+
358
+ assert_equal 0, $BEFORE_FORK_CALLED
359
+
360
+ workerA.work(0)
361
+ assert_equal 1, $BEFORE_FORK_CALLED
362
+
363
+ # TODO: Verify it's only run once. Not easy.
364
+ # workerA.work(0)
365
+ # assert_equal 1, $BEFORE_FORK_CALLED
366
+ end
367
+
368
+ test "Will call a before_fork hook before forking" do
369
+ Resque.redis.flushall
370
+ $BEFORE_FORK_CALLED = false
371
+ Resque.before_fork = Proc.new { $BEFORE_FORK_CALLED = true }
372
+ workerA = Resque::Worker.new(:jobs)
373
+
374
+ assert !$BEFORE_FORK_CALLED
375
+ Resque::Job.create(:jobs, SomeJob, 20, '/tmp')
376
+ workerA.work(0)
377
+ assert $BEFORE_FORK_CALLED
378
+ end
379
+
380
+ test "very verbose works in the afternoon" do
381
+ begin
382
+ require 'time'
383
+ last_puts = ""
384
+ Time.fake_time = Time.parse("15:44:33 2011-03-02")
385
+
386
+ @worker.extend(Module.new {
387
+ define_method(:puts) { |thing| last_puts = thing }
388
+ })
389
+
390
+ @worker.very_verbose = true
391
+ @worker.log("some log text")
392
+
393
+ assert_match /\*\* \[15:44:33 2011-03-02\] \d+: some log text/, last_puts
394
+ ensure
395
+ Time.fake_time = nil
396
+ end
397
+ end
398
+
399
+ test "Will call an after_fork hook after forking" do
400
+ Resque.redis.flushall
401
+ $AFTER_FORK_CALLED = false
402
+ Resque.after_fork = Proc.new { $AFTER_FORK_CALLED = true }
403
+ workerA = Resque::Worker.new(:jobs)
404
+
405
+ assert !$AFTER_FORK_CALLED
406
+ Resque::Job.create(:jobs, SomeJob, 20, '/tmp')
407
+ workerA.work(0)
408
+ assert $AFTER_FORK_CALLED
409
+ end
410
+
411
+ test "returns PID of running process" do
412
+ assert_equal @worker.to_s.split(":")[1].to_i, @worker.pid
413
+ end
414
+
415
+ test "requeue failed queue" do
416
+ queue = 'good_job'
417
+ Resque::Failure.create(:exception => Exception.new, :worker => Resque::Worker.new(queue), :queue => queue, :payload => {'class' => 'GoodJob'})
418
+ Resque::Failure.create(:exception => Exception.new, :worker => Resque::Worker.new(queue), :queue => 'some_job', :payload => {'class' => 'SomeJob'})
419
+ Resque::Failure.requeue_queue(queue)
420
+ assert Resque::Failure.all(0).has_key?('retried_at')
421
+ assert !Resque::Failure.all(1).has_key?('retried_at')
422
+ end
423
+
424
+ test "remove failed queue" do
425
+ queue = 'good_job'
426
+ queue2 = 'some_job'
427
+ Resque::Failure.create(:exception => Exception.new, :worker => Resque::Worker.new(queue), :queue => queue, :payload => {'class' => 'GoodJob'})
428
+ Resque::Failure.create(:exception => Exception.new, :worker => Resque::Worker.new(queue2), :queue => queue2, :payload => {'class' => 'SomeJob'})
429
+ Resque::Failure.create(:exception => Exception.new, :worker => Resque::Worker.new(queue), :queue => queue, :payload => {'class' => 'GoodJob'})
430
+ Resque::Failure.remove_queue(queue)
431
+ assert_equal queue2, Resque::Failure.all(0)['queue']
432
+ assert_equal 1, Resque::Failure.count
433
+ end
434
+ end