tr_resque 1.20.1

Sign up to get free protection for your applications and to get access to all the features.
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