QuSpec

Description

A QuSpec implements a set of matchers to help testing Qu interaction with RSpec and Cucumber. The code has been inspired by ResqueSpec but thanks to the modular architecture of Qu most of the heavy lifting has been implemented as an in-memory Qu::Backend implementation that passes the Qu test suite for backends.

Installation

# Rails 3.x: add it to your Gemfile
group :test do
  gem 'qu-spec'
end

Usage

Configuring QuSpec

To use QuSpec in your tests you need to setup Qu to use the included Memory Backend. The easiest way to accomplish this is with the QuSpec.setup! method:

RSpec.configure do |config|
  config.before do
    QuSpec.setup!
  end
end

Writing tests

Given this scenario

Given a person
When I recalculate
Then the person has calculate queued

And I write this spec using the qu-spec matcher

describe "#recalculate" do
  before do
    QuSpec.reset!
  end

  it "adds person.calculate to the Person queue" do
    person.recalculate
    Person.should have_queued(person.id, :calculate)
  end
end

(And I take note of the before block that is calling reset! for every spec)

And I might use the in statement to specify the queue:

describe "#recalculate" do
  before do
    QuSpec.reset!
  end

  it "adds person.calculate to the Person queue" do
    person.recalculate
    Person.should have_queued(person.id, :calculate).in(:people)
  end
end

And I might write this as a Cucumber step

Then /the (\w?) has (\w?) queued/ do |thing, method|
  thing_obj = instance_variable_get("@#{thing}")
  thing_obj.class.should have_queued(thing_obj.id, method.to_sym)
end

Then I write some code to make it pass:

class Person
  @queue = :people

  def recalculate
    Qu.enqueue(Person, id, :calculate)
  end
end

You can check the size of the queue in your specs too.

describe "#recalculate" do
  before do
    QuSpec.reset!
  end

  it "adds an entry to the Person queue" do
    person.recalculate
    Person.should have_queue_size_of(1)
  end
end

QuMailer with Specs

To use with QuMailer you should have an initializer that does not exclude the test (or cucumber) environment. Your initializer will probably end up looking like:

# config/initializers/qu_mailer.rb
Qu::Mailer.excluded_environments = []

QuScheduler with Specs

Support for QuScheduler is integrated into QuSpec, no additional setup is needed.

Writing tests

Given this scenario

Given a person
When I schedule a recalculate
Then the person has calculate scheduled

And I write this spec using the qu-spec matcher

describe "#recalculate" do
  before do
    QuSpec.reset!
  end

  it "adds person.calculate to the Person queue" do
    person.recalculate
    Person.should have_scheduled(person.id, :calculate)
  end
end

(And I take note of the before block that is calling reset! for every spec)

(There is also a **have_scheduled_at* matcher)*

And I might write this as a Cucumber step

Then /the (\w?) has (\w?) scheduled/ do |thing, method|
  thing_obj = instance_variable_get("@#{thing}")
  thing_obj.class.should have_scheduled(thing_obj.id, method.to_sym)
end

Then I write some code to make it pass:

class Person
  @queue = :people

  def recalculate
    Qu.enqueue_at(Time.now + 3600, Person, id, :calculate)
  end
end

Performing Jobs in Specs

QuSpec doesn't currently support performing jobs within tests. This is a feature that might get implemented in a future release.

Note on Patches / Pull Requests

  • Fork the project.
  • Make your feature addition or bug fix.
  • Add tests for it. This is important so I don't break it in a future version unintentionally.
  • Commit, do not mess with rakefile, version, or history. (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
  • Send me a pull request. Bonus points for topic branches.

Credits

This work has been heavily inspired by ResqueSpec by Les Hill.

Maintainers

License

MIT License

Copyright 2011 Morton Jonuschat
Some parts copyright 2010-2011 Les Hill