How to test Sidekiq scheduler cron jobs

RSpec

Sidekiq

Published on by

Mathieu EUSTACHY

Mathieu EUSTACHY

2 minutes reading

The sidekiq-scheduler gem is an extension to sidekiq that pushes jobs in a scheduled way, mimicking cron utility.


It is a really usefull gem I like to use on every project that requires recurring jobs. It is also quite easy to set up once installed in your app. Most of the time, I require the gem in a sidekiq.rb initializer so every jobs has access to this feature.


Once your set up is complete, you will have the ability to add schedules in your config/sidekiq.yml file.


# config/sidekiq.yml example

:schedule:
 hello_world:
  cron: '0 * * * * *'  # Runs once per minute, could also be 'every: 1 minutes'
  class: HelloWorld


I really put an emphasis to test every feature that I code in an app. This article is about implementing the corresponding tests for the :schedule: part on this file. Imagine that you change the name of a recurring job and forget to reflect the change in this file? Or you messed up your cron syntax? Well you might not see it after some time, implementing automatic testing with RSpec will remedy to that.


There are 3 things I would like to test in the example above:

- The cron syntax should be correct

- The job the task is calling should exist

- The task name should be similar to the job name


Testing the cron syntax can be achieved thanks to 'fugit' which is a dependency of sidekiq-scheduler that analyze cron syntax, the 2 remaining things to test are pretty straightforward.


It basically looks like that:


# Sidekiq-scheduler uses 'fugit' dependency under the hood to evaluate cron schedules
require "fugit"

RSpec.describe "Sidekiq Scheduler" do
 sidekiq_file = File.join(Rails.root, "config", "sidekiq.yml")
 scheduled_jobs = YAML.load_file(sidekiq_file)[:schedule]

 scheduled_jobs.each do |task_name, task_config|
  job_class = task_config["class"]
  cron = task_config["cron"] || task_config["every"] || task_config["at"] 
      || task_config["in"]

  describe "#{task_name}" do

   it "has a correct cron syntax" do
    expect { Fugit.do_parse(cron) }.not_to raise_error
   end

   it "is calling an existing job (#{job_class})" do
    expect { job_class.constantize }.not_to raise_error
   end

   it "has a correct name related to the called job" do
    expect(task_name + "_job").to eq(job_class.underscore)
   end
  end
 end
end




Resources:

- A nice Dev.to article that inspired me for setting up these tests https://dev.to/pashagray/how-to-rspec-your-sidekiq-scheduler-5hgo?signin=true

My last articles