Picky: Integration Testing

ruby / picky / testing

This is a post in the Picky series on its workings.

Let me start off by saying that it’s embarrassing that this topic is discussed only as Picky 2.3.0 is released. Especially as a proponent of test driven design. (Picky has 1300 tests and 50% more spec code than normal code)

So let’s check out how you can write the most beautifully tested Picky servers. Oh yeah.

Doin’ it

As of 2.3.0, if you use picky generate unicorn_server, you’ll get a rake spec for free which already runs integration specs on the example data.

Let’s look at the example, and after that, at each separate part.

require 'spec_helper'
require 'picky-client/spec'

describe 'Integration Tests' do

  before(:all) do
    Indexes.index_for_tests
    Indexes.load_from_cache
  end

  let(:books) { Picky::TestClient.new(PickySearch, :path => '/books') }

  # Testing a count of results.
  #
  it { books.search('a s').total.should == 42 }

  # Testing a specific order of result ids.
  #
  it { books.search('alan').ids.should == [259, 307, 449] }

  # Testing an order of result categories.
  #
  it { books.search('alan').should have_categories(['author'], ['title']) }
  it { books.search('alan p').should have_categories(['author', 'title'], ['title', 'author']) }

end

It starts off like any RSpec file, by requiring spec_helper. Then we require the spec part of the picky client.

What does it do? It provides us with the testing counterpart of the client’s Picky::Client, which is Picky::TestClient.

The test client works almost exactly like the real client, with the exception that the test client never sends HTTP requests, but uses your app’s Rack adapter. But more about that later.

require 'spec_helper'
require 'picky-client/spec'

Next, we set up the environment for the tests, i.e. get the indexes up and running.

Indexes.index_for_tests is a special index method that does not fork and runs silently (to not disturb the deadly test bugs that trawl the area).

before(:all) do
  Indexes.index_for_tests
  Indexes.load_from_cache
end

Indexes.load_from_cache loads the generated index (caches) into memory (or just leaves them alone in Redis).

Now we’re ready to do some testing!

let(:books) { Picky::TestClient.new(PickySearch, :path => '/books') }

This sets up an accessor for your tests. You give the TestClient your Application’s constant, PickySearch here, and give it the path to send queries to, here '/books'. This only works if you route the path '/books' to a Search in your application/app.rb, of course.

That’s it! Easy so far, right?

# Testing a count of results.
#
it { books.search('a s').total.should == 42 }

books is the test client we defined with the let, above. As with the normal Picky::Client, it offers a #search(text, options = {}) method.

As return value, we get a hash with the result data. However, it has already been enriched through Picky::Convenience, which you might know if you’ve set up a client webapp already.

This means we get a #total method, but also #ids, #empty?, #allocations and more which are less useful for testing.

So to test the count of results, just use #total on the result of the search.

To get a sorted array of the top ids, use – surprise – #ids.

# Testing a specific order of result ids.
#
it { books.search('alan').ids.should == [259, 307, 449] }

Also useful is to test if the category combination boosting/weights are correct. So if author, like in the first example below, should be boosted, use the have_categories matcher to check for that.

# Testing an order of result categories.
#
it { books.search('alan').should have_categories(['author'], ['title']) }
it { books.search('alan p').should have_categories(['author', 'title'], ['title', 'author']) }

And that’s how you do integration testing in Picky.

About time. Test away!

spec_helper and Rakefile

This is what your spec/spec_helper.rb would look like:

ENV['PICKY_ENV'] = 'test'

require 'picky'

SearchLog = Loggers::Search.new ::Logger.new(STDOUT)
puts "Using STDOUT as test log."

Loader.load_application

In the Rakefile just add

require 'rspec'
require 'rspec/core/rake_task'

RSpec::Core::RakeTask.new :spec

if you haven’t done this already.

Sidenote

Should any RSpec vs. Test::Unit controversy erupt around Picky… just kidding ;)

Conclusion

So we’ve seen

  1. how you do integration testing in Picky

Hope you learnt something new!

Next Picky: Environmental Considerations

Share


Previous

Comments?