From fd0232eb15f03f9633c4d4b28f9216a7d47f13a5 Mon Sep 17 00:00:00 2001 From: Ryan Schlesinger Date: Fri, 20 Sep 2013 14:39:11 -0700 Subject: [PATCH 1/2] Add dynamic testing In addition to requiring 'sidekiq/testing' and 'sidekiq/testing/inline', a user can also call the following methods to control the test harness: Sidekiq::Testing.fake! Sidekiq::Testing.inline! Sidekiq::Testing.disable! Each of the above methods also accepts a block to execute within that context before reverting to the state present before method invocation. To query the current state, use the following methods: Sidekiq::Testing.enabled? Sidekiq::Testing.disabled? Sidekiq::Testing.fake? Sidekiq::Testing.inline? Closes #1053 --- lib/sidekiq/testing.rb | 69 ++++++++- lib/sidekiq/testing/inline.rb | 67 ++++----- test/test_testing.rb | 273 ++++++---------------------------- test/test_testing_fake.rb | 265 +++++++++++++++++++++++++++++++++ test/test_testing_inline.rb | 9 +- 5 files changed, 403 insertions(+), 280 deletions(-) create mode 100644 test/test_testing_fake.rb diff --git a/lib/sidekiq/testing.rb b/lib/sidekiq/testing.rb index 3ac9db58..51b8d4a8 100644 --- a/lib/sidekiq/testing.rb +++ b/lib/sidekiq/testing.rb @@ -1,16 +1,77 @@ module Sidekiq + class Testing + class << self + attr_accessor :__test_mode + + def __set_test_mode(mode, &block) + if block + current_mode = self.__test_mode + begin + self.__test_mode = mode + block.call + ensure + self.__test_mode = current_mode + end + else + self.__test_mode = mode + end + end + + def disable!(&block) + __set_test_mode(:disable, &block) + end + + def fake!(&block) + __set_test_mode(:fake, &block) + end + + def inline!(&block) + __set_test_mode(:inline, &block) + end + + def enabled? + self.__test_mode != :disable + end + + def disabled? + self.__test_mode == :disable + end + + def fake? + self.__test_mode == :fake + end + + def inline? + self.__test_mode == :inline + end + end + end + + # Default to fake testing to keep old behavior + Sidekiq::Testing.fake! + class EmptyQueueError < RuntimeError; end class Client class << self - alias_method :raw_push_old, :raw_push + alias_method :raw_push_real, :raw_push def raw_push(payloads) - payloads.each do |job| - job['class'].constantize.jobs << Sidekiq.load_json(Sidekiq.dump_json(job)) + if Sidekiq::Testing.fake? + payloads.each do |job| + job['class'].constantize.jobs << Sidekiq.load_json(Sidekiq.dump_json(job)) + end + true + elsif Sidekiq::Testing.inline? + payloads.each do |item| + marshalled = Sidekiq.load_json(Sidekiq.dump_json(item)) + marshalled['class'].constantize.new.perform(*marshalled['args']) + end + true + else + raw_push_real(payloads) end - true end end end diff --git a/lib/sidekiq/testing/inline.rb b/lib/sidekiq/testing/inline.rb index 32123c4e..a2cb76a4 100644 --- a/lib/sidekiq/testing/inline.rb +++ b/lib/sidekiq/testing/inline.rb @@ -1,41 +1,28 @@ -module Sidekiq - class Client +require 'sidekiq/testing' - ## - # The Sidekiq inline infrastructure overrides perform_async so that it - # actually calls perform instead. This allows workers to be run inline in a - # testing environment. - # - # This is similar to `Resque.inline = true` functionality. - # - # Example: - # - # require 'sidekiq/testing/inline' - # - # $external_variable = 0 - # - # class ExternalWorker - # include Sidekiq::Worker - # - # def perform - # $external_variable = 1 - # end - # end - # - # assert_equal 0, $external_variable - # ExternalWorker.perform_async - # assert_equal 1, $external_variable - # - singleton_class.class_eval do - alias_method :raw_push_old, :raw_push - def raw_push(payload) - [payload].flatten.each do |item| - marshalled = Sidekiq.load_json(Sidekiq.dump_json(item)) - marshalled['class'].constantize.new.perform(*marshalled['args']) - end - - true - end - end - end -end +## +# The Sidekiq inline infrastructure overrides perform_async so that it +# actually calls perform instead. This allows workers to be run inline in a +# testing environment. +# +# This is similar to `Resque.inline = true` functionality. +# +# Example: +# +# require 'sidekiq/testing/inline' +# +# $external_variable = 0 +# +# class ExternalWorker +# include Sidekiq::Worker +# +# def perform +# $external_variable = 1 +# end +# end +# +# assert_equal 0, $external_variable +# ExternalWorker.perform_async +# assert_equal 1, $external_variable +# +Sidekiq::Testing.inline! diff --git a/test/test_testing.rb b/test/test_testing.rb index 950dc82d..7637a1b9 100644 --- a/test/test_testing.rb +++ b/test/test_testing.rb @@ -11,259 +11,72 @@ Sidekiq.hook_rails! class TestTesting < Sidekiq::Test describe 'sidekiq testing' do - class PerformError < RuntimeError; end - - class DirectWorker - include Sidekiq::Worker - def perform(a, b) - a + b + describe 'require/load sidekiq/testing.rb' do + before do + require 'sidekiq/testing.rb' end - end - class EnqueuedWorker - include Sidekiq::Worker - def perform(a, b) - a + b + after do + Sidekiq::Testing.disable! end - end - class StoredWorker - include Sidekiq::Worker - def perform(error) - raise PerformError if error + it 'enables fake testing' do + Sidekiq::Testing.fake! + assert_equal true, Sidekiq::Testing.enabled? + assert_equal true, Sidekiq::Testing.fake? end - end - class FooMailer < ActionMailer::Base - def bar(str) - str - end - end + it 'enables fake testing in a block' do + Sidekiq::Testing.disable! + assert_equal true, Sidekiq::Testing.disabled? - class FooModel < ActiveRecord::Base - def bar(str) - str - end - end - - before do - load 'sidekiq/testing.rb' - EnqueuedWorker.jobs.clear - DirectWorker.jobs.clear - end - - after do - # Undo override - (class << Sidekiq::Client; self; end).class_eval do - remove_method :raw_push - alias_method :raw_push, :raw_push_old - remove_method :raw_push_old - end - end - - it 'stubs the async call' do - assert_equal 0, DirectWorker.jobs.size - assert DirectWorker.perform_async(1, 2) - assert_equal 1, DirectWorker.jobs.size - assert DirectWorker.perform_in(10, 1, 2) - assert_equal 2, DirectWorker.jobs.size - assert DirectWorker.perform_at(10, 1, 2) - assert_equal 3, DirectWorker.jobs.size - assert_in_delta 10.seconds.from_now.to_f, DirectWorker.jobs.last['at'], 0.01 - end - - it 'stubs the delay call on mailers' do - assert_equal 0, Sidekiq::Extensions::DelayedMailer.jobs.size - FooMailer.delay.bar('hello!') - assert_equal 1, Sidekiq::Extensions::DelayedMailer.jobs.size - end - - class Something - def self.foo(x) - end - end - - it 'stubs the delay call on models' do - assert_equal 0, Sidekiq::Extensions::DelayedClass.jobs.size - Something.delay.foo(Date.today) - assert_equal 1, Sidekiq::Extensions::DelayedClass.jobs.size - end - - it 'stubs the enqueue call' do - assert_equal 0, EnqueuedWorker.jobs.size - assert Sidekiq::Client.enqueue(EnqueuedWorker, 1, 2) - assert_equal 1, EnqueuedWorker.jobs.size - end - - it 'stubs the enqueue_to call' do - assert_equal 0, EnqueuedWorker.jobs.size - assert Sidekiq::Client.enqueue_to('someq', EnqueuedWorker, 1, 2) - assert_equal 1, EnqueuedWorker.jobs.size - end - - it 'executes all stored jobs' do - assert StoredWorker.perform_async(false) - assert StoredWorker.perform_async(true) - - assert_equal 2, StoredWorker.jobs.size - assert_raises PerformError do - StoredWorker.drain - end - assert_equal 0, StoredWorker.jobs.size - - end - - class SpecificJidWorker - include Sidekiq::Worker - class_attribute :count - self.count = 0 - def perform(worker_jid) - return unless worker_jid == self.jid - self.class.count += 1 - end - end - - it 'execute only jobs with assigned JID' do - 4.times do |i| - jid = SpecificJidWorker.perform_async(nil) - if i % 2 == 0 - SpecificJidWorker.jobs[-1]["args"] = ["wrong_jid"] - else - SpecificJidWorker.jobs[-1]["args"] = [jid] + Sidekiq::Testing.fake! do + assert_equal true, Sidekiq::Testing.enabled? + assert_equal true, Sidekiq::Testing.fake? end + + assert_equal false, Sidekiq::Testing.enabled? + assert_equal false, Sidekiq::Testing.fake? end - SpecificJidWorker.perform_one - assert_equal 0, SpecificJidWorker.count + it 'disables testing in a block' do + Sidekiq::Testing.fake! - SpecificJidWorker.perform_one - assert_equal 1, SpecificJidWorker.count + Sidekiq::Testing.disable! do + assert_equal true, Sidekiq::Testing.disabled? + end - SpecificJidWorker.drain - assert_equal 2, SpecificJidWorker.count - end - - it 'round trip serializes the job arguments' do - assert StoredWorker.perform_async(:mike) - job = StoredWorker.jobs.first - assert_equal "mike", job['args'].first - StoredWorker.clear - end - - it 'perform_one runs only one job' do - DirectWorker.perform_async(1, 2) - DirectWorker.perform_async(3, 4) - assert_equal 2, DirectWorker.jobs.size - - DirectWorker.perform_one - assert_equal 1, DirectWorker.jobs.size - - DirectWorker.clear - end - - it 'perform_one raise error upon empty queue' do - DirectWorker.clear - assert_raises Sidekiq::EmptyQueueError do - DirectWorker.perform_one + assert_equal true, Sidekiq::Testing.enabled? end end - class FirstWorker - include Sidekiq::Worker - class_attribute :count - self.count = 0 - def perform - self.class.count += 1 + describe 'require/load sidekiq/testing/inline.rb' do + before do + require 'sidekiq/testing/inline.rb' end - end - class SecondWorker - include Sidekiq::Worker - class_attribute :count - self.count = 0 - def perform - self.class.count += 1 + after do + Sidekiq::Testing.disable! end - end - class ThirdWorker - include Sidekiq::Worker - class_attribute :count - def perform - FirstWorker.perform_async - SecondWorker.perform_async + it 'enables inline testing' do + Sidekiq::Testing.inline! + assert_equal true, Sidekiq::Testing.enabled? + assert_equal true, Sidekiq::Testing.inline? end - end - it 'clears jobs across all workers' do - Sidekiq::Worker.jobs.clear - FirstWorker.count = 0 - SecondWorker.count = 0 + it 'enables inline testing in a block' do + Sidekiq::Testing.disable! + assert_equal true, Sidekiq::Testing.disabled? - assert_equal 0, FirstWorker.jobs.size - assert_equal 0, SecondWorker.jobs.size + Sidekiq::Testing.inline! do + assert_equal true, Sidekiq::Testing.enabled? + assert_equal true, Sidekiq::Testing.inline? + end - FirstWorker.perform_async - SecondWorker.perform_async - - assert_equal 1, FirstWorker.jobs.size - assert_equal 1, SecondWorker.jobs.size - - Sidekiq::Worker.clear_all - - assert_equal 0, FirstWorker.jobs.size - assert_equal 0, SecondWorker.jobs.size - - assert_equal 0, FirstWorker.count - assert_equal 0, SecondWorker.count - end - - it 'drains jobs across all workers' do - Sidekiq::Worker.jobs.clear - FirstWorker.count = 0 - SecondWorker.count = 0 - - assert_equal 0, FirstWorker.jobs.size - assert_equal 0, SecondWorker.jobs.size - - assert_equal 0, FirstWorker.count - assert_equal 0, SecondWorker.count - - FirstWorker.perform_async - SecondWorker.perform_async - - assert_equal 1, FirstWorker.jobs.size - assert_equal 1, SecondWorker.jobs.size - - Sidekiq::Worker.drain_all - - assert_equal 0, FirstWorker.jobs.size - assert_equal 0, SecondWorker.jobs.size - - assert_equal 1, FirstWorker.count - assert_equal 1, SecondWorker.count - end - - it 'drains jobs across all workers even when workers create new jobs' do - Sidekiq::Worker.jobs.clear - FirstWorker.count = 0 - SecondWorker.count = 0 - - assert_equal 0, ThirdWorker.jobs.size - - assert_equal 0, FirstWorker.count - assert_equal 0, SecondWorker.count - - ThirdWorker.perform_async - - assert_equal 1, ThirdWorker.jobs.size - - Sidekiq::Worker.drain_all - - assert_equal 0, ThirdWorker.jobs.size - - assert_equal 1, FirstWorker.count - assert_equal 1, SecondWorker.count + assert_equal false, Sidekiq::Testing.enabled? + assert_equal false, Sidekiq::Testing.inline? + end end end end diff --git a/test/test_testing_fake.rb b/test/test_testing_fake.rb new file mode 100644 index 00000000..eb6214f4 --- /dev/null +++ b/test/test_testing_fake.rb @@ -0,0 +1,265 @@ +require 'helper' +require 'sidekiq' +require 'sidekiq/worker' +require 'active_record' +require 'action_mailer' +require 'sidekiq/rails' +require 'sidekiq/extensions/action_mailer' +require 'sidekiq/extensions/active_record' + +Sidekiq.hook_rails! + +class TestTesting < Sidekiq::Test + describe 'sidekiq testing' do + class PerformError < RuntimeError; end + + class DirectWorker + include Sidekiq::Worker + def perform(a, b) + a + b + end + end + + class EnqueuedWorker + include Sidekiq::Worker + def perform(a, b) + a + b + end + end + + class StoredWorker + include Sidekiq::Worker + def perform(error) + raise PerformError if error + end + end + + class FooMailer < ActionMailer::Base + def bar(str) + str + end + end + + class FooModel < ActiveRecord::Base + def bar(str) + str + end + end + + before do + require 'sidekiq/testing.rb' + Sidekiq::Testing.fake! + EnqueuedWorker.jobs.clear + DirectWorker.jobs.clear + end + + after do + Sidekiq::Testing.disable! + end + + it 'stubs the async call' do + assert_equal 0, DirectWorker.jobs.size + assert DirectWorker.perform_async(1, 2) + assert_equal 1, DirectWorker.jobs.size + assert DirectWorker.perform_in(10, 1, 2) + assert_equal 2, DirectWorker.jobs.size + assert DirectWorker.perform_at(10, 1, 2) + assert_equal 3, DirectWorker.jobs.size + assert_in_delta 10.seconds.from_now.to_f, DirectWorker.jobs.last['at'], 0.01 + end + + it 'stubs the delay call on mailers' do + assert_equal 0, Sidekiq::Extensions::DelayedMailer.jobs.size + FooMailer.delay.bar('hello!') + assert_equal 1, Sidekiq::Extensions::DelayedMailer.jobs.size + end + + class Something + def self.foo(x) + end + end + + it 'stubs the delay call on models' do + assert_equal 0, Sidekiq::Extensions::DelayedClass.jobs.size + Something.delay.foo(Date.today) + assert_equal 1, Sidekiq::Extensions::DelayedClass.jobs.size + end + + it 'stubs the enqueue call' do + assert_equal 0, EnqueuedWorker.jobs.size + assert Sidekiq::Client.enqueue(EnqueuedWorker, 1, 2) + assert_equal 1, EnqueuedWorker.jobs.size + end + + it 'stubs the enqueue_to call' do + assert_equal 0, EnqueuedWorker.jobs.size + assert Sidekiq::Client.enqueue_to('someq', EnqueuedWorker, 1, 2) + assert_equal 1, EnqueuedWorker.jobs.size + end + + it 'executes all stored jobs' do + assert StoredWorker.perform_async(false) + assert StoredWorker.perform_async(true) + + assert_equal 2, StoredWorker.jobs.size + assert_raises PerformError do + StoredWorker.drain + end + assert_equal 0, StoredWorker.jobs.size + + end + + class SpecificJidWorker + include Sidekiq::Worker + class_attribute :count + self.count = 0 + def perform(worker_jid) + return unless worker_jid == self.jid + self.class.count += 1 + end + end + + it 'execute only jobs with assigned JID' do + 4.times do |i| + jid = SpecificJidWorker.perform_async(nil) + if i % 2 == 0 + SpecificJidWorker.jobs[-1]["args"] = ["wrong_jid"] + else + SpecificJidWorker.jobs[-1]["args"] = [jid] + end + end + + SpecificJidWorker.perform_one + assert_equal 0, SpecificJidWorker.count + + SpecificJidWorker.perform_one + assert_equal 1, SpecificJidWorker.count + + SpecificJidWorker.drain + assert_equal 2, SpecificJidWorker.count + end + + it 'round trip serializes the job arguments' do + assert StoredWorker.perform_async(:mike) + job = StoredWorker.jobs.first + assert_equal "mike", job['args'].first + StoredWorker.clear + end + + it 'perform_one runs only one job' do + DirectWorker.perform_async(1, 2) + DirectWorker.perform_async(3, 4) + assert_equal 2, DirectWorker.jobs.size + + DirectWorker.perform_one + assert_equal 1, DirectWorker.jobs.size + + DirectWorker.clear + end + + it 'perform_one raise error upon empty queue' do + DirectWorker.clear + assert_raises Sidekiq::EmptyQueueError do + DirectWorker.perform_one + end + end + + class FirstWorker + include Sidekiq::Worker + class_attribute :count + self.count = 0 + def perform + self.class.count += 1 + end + end + + class SecondWorker + include Sidekiq::Worker + class_attribute :count + self.count = 0 + def perform + self.class.count += 1 + end + end + + class ThirdWorker + include Sidekiq::Worker + class_attribute :count + def perform + FirstWorker.perform_async + SecondWorker.perform_async + end + end + + it 'clears jobs across all workers' do + Sidekiq::Worker.jobs.clear + FirstWorker.count = 0 + SecondWorker.count = 0 + + assert_equal 0, FirstWorker.jobs.size + assert_equal 0, SecondWorker.jobs.size + + FirstWorker.perform_async + SecondWorker.perform_async + + assert_equal 1, FirstWorker.jobs.size + assert_equal 1, SecondWorker.jobs.size + + Sidekiq::Worker.clear_all + + assert_equal 0, FirstWorker.jobs.size + assert_equal 0, SecondWorker.jobs.size + + assert_equal 0, FirstWorker.count + assert_equal 0, SecondWorker.count + end + + it 'drains jobs across all workers' do + Sidekiq::Worker.jobs.clear + FirstWorker.count = 0 + SecondWorker.count = 0 + + assert_equal 0, FirstWorker.jobs.size + assert_equal 0, SecondWorker.jobs.size + + assert_equal 0, FirstWorker.count + assert_equal 0, SecondWorker.count + + FirstWorker.perform_async + SecondWorker.perform_async + + assert_equal 1, FirstWorker.jobs.size + assert_equal 1, SecondWorker.jobs.size + + Sidekiq::Worker.drain_all + + assert_equal 0, FirstWorker.jobs.size + assert_equal 0, SecondWorker.jobs.size + + assert_equal 1, FirstWorker.count + assert_equal 1, SecondWorker.count + end + + it 'drains jobs across all workers even when workers create new jobs' do + Sidekiq::Worker.jobs.clear + FirstWorker.count = 0 + SecondWorker.count = 0 + + assert_equal 0, ThirdWorker.jobs.size + + assert_equal 0, FirstWorker.count + assert_equal 0, SecondWorker.count + + ThirdWorker.perform_async + + assert_equal 1, ThirdWorker.jobs.size + + Sidekiq::Worker.drain_all + + assert_equal 0, ThirdWorker.jobs.size + + assert_equal 1, FirstWorker.count + assert_equal 1, SecondWorker.count + end + end +end diff --git a/test/test_testing_inline.rb b/test/test_testing_inline.rb index 202591aa..9801a55d 100644 --- a/test/test_testing_inline.rb +++ b/test/test_testing_inline.rb @@ -41,15 +41,12 @@ class TestInline < Sidekiq::Test end before do - load 'sidekiq/testing/inline.rb' + require 'sidekiq/testing/inline.rb' + Sidekiq::Testing.inline! end after do - Sidekiq::Client.singleton_class.class_eval do - remove_method :raw_push - alias_method :raw_push, :raw_push_old - remove_method :raw_push_old - end + Sidekiq::Testing.disable! end it 'stubs the async call when in testing mode' do From 5deb79d6a2f082f1558d6732c97e05b3ed8724a6 Mon Sep 17 00:00:00 2001 From: Hernan Astudillo A Date: Thu, 26 Sep 2013 22:47:53 -0300 Subject: [PATCH 2/2] improve usability on mobile-ui for redis stats on dashboard --- web/assets/stylesheets/application.css | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/web/assets/stylesheets/application.css b/web/assets/stylesheets/application.css index 911cbb38..357566e1 100755 --- a/web/assets/stylesheets/application.css +++ b/web/assets/stylesheets/application.css @@ -290,7 +290,6 @@ img.smallogo { .poll-status { padding: 10px 0; } - .stat { float: left; text-align: center; @@ -304,7 +303,23 @@ img.smallogo { .stat p { font-size: 0.9em; } - +@media (max-width: 767px) { + .stat { + float: none; + margin-right: 10px; + width: 100%; + text-align: left; + line-height: 45px; + } + .stat h3{ + float: right; + margin: 5px 10px 5px 5px; + } + .stat p{ + font-size: normal; + margin: 5px 5px 5px 10px; + } +} .beacon { position: relative; height: 20px;