1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00

Add an :only option to perform_enqueued_jobs to filter jobs based on

type.

This allows specific jobs to be tested, while preventing others from
being performed unnecessarily.

Example:

    def test_hello_job
      assert_performed_jobs 1, only: HelloJob do
        HelloJob.perform_later('jeremy')
        LoggingJob.perform_later
      end
    end

An array may also be specified, to support testing multiple jobs.

Example:

    def test_hello_and_logging_jobs
      assert_nothing_raised do
        assert_performed_jobs 2, only: [HelloJob, LoggingJob] do
          HelloJob.perform_later('jeremy')
          LoggingJob.perform_later('stewie')
          RescueJob.perform_later('david')
        end
      end
    end

Fixes #18802.

Trim space and document :only option.
This commit is contained in:
Michael Ryan 2015-02-06 13:05:28 -05:00
parent ec6c98f7d1
commit e818f65770
4 changed files with 186 additions and 18 deletions

View file

@ -44,5 +44,39 @@
*Isaac Seymour* *Isaac Seymour*
* Add an `:only` option to `perform_enqueued_jobs` to filter jobs based on
type.
This allows specific jobs to be tested, while preventing others from
being performed unnecessarily.
Example:
def test_hello_job
assert_performed_jobs 1, only: HelloJob do
HelloJob.perform_later('jeremy')
LoggingJob.perform_later
end
end
An array may also be specified, to support testing multiple jobs.
Example:
def test_hello_and_logging_jobs
assert_nothing_raised do
assert_performed_jobs 2, only: [HelloJob, LoggingJob] do
HelloJob.perform_later('jeremy')
LoggingJob.perform_later('stewie')
RescueJob.perform_later('david')
end
end
end
Fixes #18802.
*Michael Ryan*
Please check [4-2-stable](https://github.com/rails/rails/blob/4-2-stable/activejob/CHANGELOG.md) for previous changes. Please check [4-2-stable](https://github.com/rails/rails/blob/4-2-stable/activejob/CHANGELOG.md) for previous changes.

View file

@ -11,7 +11,7 @@ module ActiveJob
# Rails.application.config.active_job.queue_adapter = :test # Rails.application.config.active_job.queue_adapter = :test
class TestAdapter class TestAdapter
delegate :name, to: :class delegate :name, to: :class
attr_accessor(:perform_enqueued_jobs, :perform_enqueued_at_jobs) attr_accessor(:perform_enqueued_jobs, :perform_enqueued_at_jobs, :filter)
attr_writer(:enqueued_jobs, :performed_jobs) attr_writer(:enqueued_jobs, :performed_jobs)
def initialize def initialize
@ -30,22 +30,33 @@ module ActiveJob
end end
def enqueue(job) #:nodoc: def enqueue(job) #:nodoc:
if perform_enqueued_jobs return if filtered?(job)
performed_jobs << {job: job.class, args: job.serialize['arguments'], queue: job.queue_name}
Base.execute job.serialize job_data = { job: job.class, args: job.serialize['arguments'], queue: job.queue_name }
else enqueue_or_perform(perform_enqueued_jobs, job, job_data)
enqueued_jobs << {job: job.class, args: job.serialize['arguments'], queue: job.queue_name}
end
end end
def enqueue_at(job, timestamp) #:nodoc: def enqueue_at(job, timestamp) #:nodoc:
if perform_enqueued_at_jobs return if filtered?(job)
performed_jobs << {job: job.class, args: job.serialize['arguments'], queue: job.queue_name, at: timestamp}
job_data = { job: job.class, args: job.serialize['arguments'], queue: job.queue_name, at: timestamp }
enqueue_or_perform(perform_enqueued_at_jobs, job, job_data)
end
private
def enqueue_or_perform(perform, job, job_data)
if perform
performed_jobs << job_data
Base.execute job.serialize Base.execute job.serialize
else else
enqueued_jobs << {job: job.class, args: job.serialize['arguments'], queue: job.queue_name, at: timestamp} enqueued_jobs << job_data
end end
end end
def filtered?(job)
filter && !Array(filter).include?(job.class)
end
end end
end end
end end

View file

@ -125,10 +125,32 @@ module ActiveJob
# HelloJob.perform_later('sean') # HelloJob.perform_later('sean')
# end # end
# end # end
def assert_performed_jobs(number) #
# The block form supports filtering. If the :only option is specified,
# then only the listed job(s) will be performed.
#
# def test_hello_job
# assert_performed_jobs 1, only: HelloJob do
# HelloJob.perform_later('jeremy')
# LoggingJob.perform_later
# end
# end
#
# An array may also be specified, to support testing multiple jobs.
#
# def test_hello_and_logging_jobs
# assert_nothing_raised do
# assert_performed_jobs 2, only: [HelloJob, LoggingJob] do
# HelloJob.perform_later('jeremy')
# LoggingJob.perform_later('stewie')
# RescueJob.perform_later('david')
# end
# end
# end
def assert_performed_jobs(number, only: nil)
if block_given? if block_given?
original_count = performed_jobs.size original_count = performed_jobs.size
perform_enqueued_jobs { yield } perform_enqueued_jobs(only: only) { yield }
new_count = performed_jobs.size new_count = performed_jobs.size
assert_equal original_count + number, new_count, assert_equal original_count + number, new_count,
"#{number} jobs expected, but #{new_count - original_count} were performed" "#{number} jobs expected, but #{new_count - original_count} were performed"
@ -157,11 +179,33 @@ module ActiveJob
# end # end
# end # end
# #
# The block form supports filtering. If the :only option is specified,
# then only the listed job(s) will be performed.
#
# def test_hello_job
# assert_performed_jobs 1, only: HelloJob do
# HelloJob.perform_later('jeremy')
# LoggingJob.perform_later
# end
# end
#
# An array may also be specified, to support testing multiple jobs.
#
# def test_hello_and_logging_jobs
# assert_nothing_raised do
# assert_performed_jobs 2, only: [HelloJob, LoggingJob] do
# HelloJob.perform_later('jeremy')
# LoggingJob.perform_later('stewie')
# RescueJob.perform_later('david')
# end
# end
# end
#
# Note: This assertion is simply a shortcut for: # Note: This assertion is simply a shortcut for:
# #
# assert_performed_jobs 0, &block # assert_performed_jobs 0, &block
def assert_no_performed_jobs(&block) def assert_no_performed_jobs(only: nil, &block)
assert_performed_jobs 0, &block assert_performed_jobs 0, only: only, &block
end end
# Asserts that the job passed in the block has been enqueued with the given arguments. # Asserts that the job passed in the block has been enqueued with the given arguments.
@ -206,11 +250,12 @@ module ActiveJob
queue_adapter.performed_jobs = original_performed_jobs + performed_jobs queue_adapter.performed_jobs = original_performed_jobs + performed_jobs
end end
def perform_enqueued_jobs def perform_enqueued_jobs(only: nil)
@old_perform_enqueued_jobs = queue_adapter.perform_enqueued_jobs @old_perform_enqueued_jobs = queue_adapter.perform_enqueued_jobs
@old_perform_enqueued_at_jobs = queue_adapter.perform_enqueued_at_jobs @old_perform_enqueued_at_jobs = queue_adapter.perform_enqueued_at_jobs
queue_adapter.perform_enqueued_jobs = true queue_adapter.perform_enqueued_jobs = true
queue_adapter.perform_enqueued_at_jobs = true queue_adapter.perform_enqueued_at_jobs = true
queue_adapter.filter = only
yield yield
ensure ensure
queue_adapter.perform_enqueued_jobs = @old_perform_enqueued_jobs queue_adapter.perform_enqueued_jobs = @old_perform_enqueued_jobs

View file

@ -4,6 +4,7 @@ require 'active_support/core_ext/date'
require 'jobs/hello_job' require 'jobs/hello_job'
require 'jobs/logging_job' require 'jobs/logging_job'
require 'jobs/nested_job' require 'jobs/nested_job'
require 'jobs/rescue_job'
require 'models/person' require 'models/person'
class EnqueuedJobsTest < ActiveJob::TestCase class EnqueuedJobsTest < ActiveJob::TestCase
@ -283,6 +284,83 @@ class PerformedJobsTest < ActiveJob::TestCase
assert_match(/0 .* but 1/, error.message) assert_match(/0 .* but 1/, error.message)
end end
def test_assert_performed_jobs_with_only_option
assert_nothing_raised do
assert_performed_jobs 1, only: HelloJob do
HelloJob.perform_later('jeremy')
LoggingJob.perform_later
end
end
end
def test_assert_performed_jobs_with_only_option_as_array
assert_nothing_raised do
assert_performed_jobs 2, only: [HelloJob, LoggingJob] do
HelloJob.perform_later('jeremy')
LoggingJob.perform_later('stewie')
RescueJob.perform_later('david')
end
end
end
def test_assert_performed_jobs_with_only_option_and_none_sent
error = assert_raise ActiveSupport::TestCase::Assertion do
assert_performed_jobs 1, only: HelloJob do
LoggingJob.perform_later
end
end
assert_match(/1 .* but 0/, error.message)
end
def test_assert_performed_jobs_with_only_option_and_too_few_sent
error = assert_raise ActiveSupport::TestCase::Assertion do
assert_performed_jobs 5, only: HelloJob do
HelloJob.perform_later('jeremy')
4.times { LoggingJob.perform_later }
end
end
assert_match(/5 .* but 1/, error.message)
end
def test_assert_performed_jobs_with_only_option_and_too_many_sent
error = assert_raise ActiveSupport::TestCase::Assertion do
assert_performed_jobs 1, only: HelloJob do
2.times { HelloJob.perform_later('jeremy') }
end
end
assert_match(/1 .* but 2/, error.message)
end
def test_assert_no_performed_jobs_with_only_option
assert_nothing_raised do
assert_no_performed_jobs only: HelloJob do
LoggingJob.perform_later
end
end
end
def test_assert_no_performed_jobs_with_only_option_as_array
assert_nothing_raised do
assert_no_performed_jobs only: [HelloJob, RescueJob] do
LoggingJob.perform_later
end
end
end
def test_assert_no_performed_jobs_with_only_option_failure
error = assert_raise ActiveSupport::TestCase::Assertion do
assert_no_performed_jobs only: HelloJob do
HelloJob.perform_later('jeremy')
LoggingJob.perform_later
end
end
assert_match(/0 .* but 1/, error.message)
end
def test_assert_performed_job def test_assert_performed_job
assert_performed_with(job: NestedJob, queue: 'default') do assert_performed_with(job: NestedJob, queue: 'default') do
NestedJob.perform_later NestedJob.perform_later