Skip to content

Commit

Permalink
Merge pull request #75 from Shopify/consolidate-integration-tests
Browse files Browse the repository at this point in the history
Extract common `IntegrationBehaviour` test module
  • Loading branch information
azuredeviil053 committed Apr 19, 2021
2 parents b235322 + a3c83e3 commit 630fbe7
Show file tree
Hide file tree
Showing 3 changed files with 101 additions and 95 deletions.
81 changes: 81 additions & 0 deletions test/integration/integration_behaviour.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# frozen_string_literal: true

module IntegrationBehaviour
extend ActiveSupport::Concern

included do
setup do
@original_adapter = ActiveJob::Base.queue_adapter
ActiveJob::Base.queue_adapter = queue_adapter
end

teardown do
ActiveJob::Base.queue_adapter = @original_adapter
end

test "interrupts the job" do
IterationJob.perform_later

start_worker_and_wait

assert_equal 1, queue_size
assert_equal 0, job_args.dig(0, "cursor_position")
assert_equal 1, job_args.dig(0, "times_interrupted")

start_worker_and_wait

assert_equal 1, queue_size
assert_equal 2, job_args.dig(0, "cursor_position")
assert_equal 2, job_args.dig(0, "times_interrupted")

TerminateJob.perform_later
start_worker_and_wait

assert_equal 0, queue_size
end

test "unserializable corruption is prevented" do
# Cursors are serialized as JSON, but not all objects are serializable.
# time = Time.at(0).utc # => 1970-01-01 00:00:00 UTC
# json = JSON.dump(time) # => "\"1970-01-01 00:00:00 UTC\""
# string = JSON.parse(json) # => "1970-01-01 00:00:00 UTC"
# We serialized a Time, but it was deserialized as a String.
TimeCursorJob.perform_later
TerminateJob.perform_later
start_worker_and_wait

assert_equal(
JobIteration::Iteration::CursorError.name,
failed_job_error_class_name,
)
end

private

# Should return the symbol to use when configuring the adapter
# ActiveJob::Base.queue_adapter = adapter
def adapter
raise NotImplemented, "#{self.class.name} must implement #{__method__}"
end

# Should start the job worker process and allow it to work the queue
def start_worker_and_wait
raise NotImplemented, "#{self.class.name} must implement #{__method__}"
end

# Should return the number of jobs currently enqueued for processing
def queue_size
raise NotImplemented, "#{self.class.name} must implement #{__method__}"
end

# Should return the hash of job arguments belonging to the most recently enqueued job
def job_args
raise NotImplemented, "#{self.class.name} must implement #{__method__}"
end

# Should return a String matching the name of the error class of the most recently failed job
def failed_job_error_class_name
raise NotImplemented, "#{self.class.name} must implement #{__method__}"
end
end
end
57 changes: 10 additions & 47 deletions test/integration/resque_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,59 +3,18 @@
require "test_helper"

require_relative "../support/jobs"
require_relative "integration_behaviour"

class ResqueIntegrationTest < ActiveSupport::TestCase
setup do
@original_adapter = ActiveJob::Base.queue_adapter
ActiveJob::Base.queue_adapter = :resque
end

teardown do
ActiveJob::Base.queue_adapter = @original_adapter
end

test "interrupts the job" do
IterationJob.perform_later

start_resque_and_wait

assert_equal 1, queue_size
job_args = jobs_in_queue.first.fetch("args")
assert_equal 0, job_args.dig(0, "cursor_position")
assert_equal 1, job_args.dig(0, "times_interrupted")

start_resque_and_wait

assert_equal 1, queue_size
job_args = jobs_in_queue.first.fetch("args")
assert_equal 2, job_args.dig(0, "cursor_position")
assert_equal 2, job_args.dig(0, "times_interrupted")
include IntegrationBehaviour

TerminateJob.perform_later
start_resque_and_wait

assert_equal 0, queue_size
end

test "unserializable corruption is prevented" do
# Resque serializes cursors as JSON, but not all objects are serializable.
# time = Time.at(0).utc # => 1970-01-01 00:00:00 UTC
# json = JSON.dump(time) # => "\"1970-01-01 00:00:00 UTC\""
# string = JSON.parse(json) # => "1970-01-01 00:00:00 UTC"
# We serialized a Time, but it was deserialized as a String.
TimeCursorJob.perform_later
TerminateJob.perform_later
start_resque_and_wait
private

assert_equal(
JobIteration::Iteration::CursorError.name,
failed_job_error_class_name,
)
def queue_adapter
:resque
end

private

def start_resque_and_wait
def start_worker_and_wait
pid = nil
Dir.chdir("test/support/resque") do
pid = spawn(resque_env, "bundle exec rake resque:work")
Expand All @@ -78,6 +37,10 @@ def queue_size
Resque.queue_sizes.fetch("default")
end

def job_args
jobs_in_queue.first.fetch("args")
end

def jobs_in_queue
Resque.redis.lrange("queue:default", 0, -1).map { |payload| JSON.parse(payload) }
end
Expand Down
58 changes: 10 additions & 48 deletions test/integration/sidekiq_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,60 +4,18 @@

require "sidekiq/api"
require_relative "../support/jobs"
require_relative "integration_behaviour"

class SidekiqIntegrationTest < ActiveSupport::TestCase
setup do
@original_adapter = ActiveJob::Base.queue_adapter
ActiveJob::Base.queue_adapter = :sidekiq
end

teardown do
ActiveJob::Base.queue_adapter = @original_adapter
end

test "interrupts the job" do
IterationJob.perform_later

start_sidekiq_and_wait

assert_equal 1, queue_size

job_args = Sidekiq::Queue.new.first.args
assert_equal 0, job_args.dig(0, "cursor_position")
assert_equal 1, job_args.dig(0, "times_interrupted")

start_sidekiq_and_wait

assert_equal 1, queue_size
job_args = Sidekiq::Queue.new.first.args
assert_equal 2, job_args.dig(0, "cursor_position")
assert_equal 2, job_args.dig(0, "times_interrupted")
include IntegrationBehaviour

TerminateJob.perform_later
start_sidekiq_and_wait

assert_equal 0, queue_size
end

test "unserializable cursor corruption is prevented" do
# Sidekiq serializes cursors as JSON, but not all objects are serializable.
# time = Time.at(0).utc # => 1970-01-01 00:00:00 UTC
# json = JSON.dump(time) # => "\"1970-01-01 00:00:00 UTC\""
# string = JSON.parse(json) # => "1970-01-01 00:00:00 UTC"
# We serialized a Time, but it was deserialized as a String.
TimeCursorJob.perform_later
TerminateJob.perform_later
start_sidekiq_and_wait
private

assert_equal(
JobIteration::Iteration::CursorError.name,
failed_job_error_class_name,
)
def queue_adapter
:sidekiq
end

private

def start_sidekiq_and_wait
def start_worker_and_wait
pid = spawn("bundle exec sidekiq -r ./test/support/sidekiq/init.rb -c 1")
ensure
Process.wait(pid)
Expand All @@ -67,6 +25,10 @@ def queue_size
Sidekiq::Queue.new.size
end

def job_args
Sidekiq::Queue.new.first.args
end

def failed_job_error_class_name
Sidekiq::RetrySet.new.first&.item&.fetch("error_class")
end
Expand Down

0 comments on commit 630fbe7

Please sign in to comment.